// Snapped Labels, "Voxel exact" tab: per-scroll claim levels (Measured, Certified, Not shown), tolerance bars, abstain // strata, residual histograms and controls, read from vx/summary.json (schema snapped-labels/voxel-exact@1, checked by // python -m kit vxsummary check). ?vx=URL reads another summary; ?vx=fixture reads the synthetic fixture, always under a // banner. The tab stays hidden until a summary loads and validates. Loaded after app.js and uses its helpers. 'use strict'; const VX = { doc: null, url: null, fixture: false, show: null, showIdx: 0, mode: 'signed', pick: {} }; const VX_SCHEMA = 'snapped-labels/voxel-exact@1'; const VX_CLAIMS = { measured: 'Measured', certified: 'Certified', not_shown: 'Not shown' }; const VX_ORDER = { measured: 0, certified: 1, not_shown: 2 }; const VX_TOLS = ['0.5', '1', '2']; // a verdict is text plus a shape, never color alone const VX_ICON = { PASS: '✓', FAIL: '✕', 'NOT SHOWN': '○', UNANSWERABLE: '?', VOID: '⊘' }; const VX_STRATUM_NAME = { C0: 'snapped (code 0)', C0L: 'snapped, placed in the label scan (code 0)', C2: 'filled (code 2)', C1: 'left in place (code 1)' }; const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); const p1 = (x) => (x == null || !Number.isFinite(x) ? 'n/a' : `${(100 * x).toFixed(1)}%`); const sgn = (x) => (x > 0 ? `+${x.toFixed(2)}` : x.toFixed(2)); const VX_BASIS = { itt: 'every selected site', scorable: 'scorable sites', covered: 'covered sites' }; function vxURL() { const q = params.get('vx'); if (q === 'fixture') return new URL('vx/fixture/summary.json', location.href).href; return new URL(q || 'vx/summary.json', location.href).href; } // The page's own check, a subset of kit/vxsummary.py: enough that a broken file never draws as numbers. function vxValid(d) { const bad = []; if (!d || d.schema !== VX_SCHEMA) bad.push(`schema is not ${VX_SCHEMA}`); if (!d || !Array.isArray(d.scrolls) || !d.scrolls.length) bad.push('no scrolls'); // every count drawn into the page must be an integer and every share a number in 0..1, so a file from ?vx=URL // cannot carry markup into the cards const cnt = (x) => Number.isInteger(x) && x >= 0; const frac = (x) => x == null || (typeof x === 'number' && x >= 0 && x <= 1); const slotOK = (w) => !w || (cnt(w.k) && cnt(w.n) && w.k <= w.n && frac(w.share) && frac(w.lower) && frac(w.upper) && w.basis in VX_BASIS); for (const s of (d && d.scrolls) || []) { if (!(s.claim in VX_CLAIMS)) bad.push(`${s.scroll}: claim ${s.claim}`); for (const st of s.strata || []) { if (!cnt(st.n_selected) || !cnt(st.n_scorable)) bad.push(`${s.scroll} ${st.id} counts`); const c = st.coverage; if (c && !(cnt(c.k) && cnt(c.n) && c.k <= c.n && frac(c.share) && frac(c.lower) && frac(c.upper) && frac(c.bar))) bad.push(`${s.scroll} ${st.id} coverage`); if (st.single_truth && !slotOK(st.single_truth.within_1)) bad.push(`${s.scroll} ${st.id} single_truth`); for (const t of VX_TOLS) if (!slotOK(st.within && st.within[t])) bad.push(`${s.scroll} ${st.id} within ${t} slot`); if (st.median_abs != null && typeof st.median_abs !== 'number') bad.push(`${s.scroll} ${st.id} median`); } for (const st of s.strata || []) for (const t of VX_TOLS) { const w = st.within && st.within[t]; if (w && !(w.n >= w.k && w.k >= 0 && w.share >= 0 && w.share <= 1)) bad.push(`${s.scroll} ${st.id} within ${t}`); if (w && w.basis === 'covered' && !(st.coverage && st.coverage.k === w.n)) bad.push(`${s.scroll} ${st.id} covered ${t}`); } if ((s.strata || []).some((st) => st.coverage) && !s.scope) bad.push(`${s.scroll}: a two-scan test without its scope`); } if (d && typeof d.fixture !== 'boolean') bad.push('fixture flag missing'); return bad; } // ---------------------------------------------------------------- small charts function tolBars(st, rule) { const bar = rule && rule.bar != null ? rule.bar : 0.9; return `
${VX_TOLS.map((t) => { const w = st.within[t]; const label = `${t === '1' ? '1 voxel' : `${t} voxels`}`; if (!w) return `
${label}not measuredn/a
`; const lo = w.lower != null ? w.lower : null, hi = w.upper != null ? w.upper : null; const whisk = lo != null ? `` : ''; const line = t === '1' ? `` : ''; return `
${label} ${whisk}${line} ${p1(w.share)} ${esc(w.k)} of ${esc(w.n)}, ${VX_BASIS[w.basis] || w.basis}
`; }).join('')}
`; } // a two-scan test: the share of drawn sites the two scans cover, with its interval and bar function coverageBar(st) { const c = st.coverage; if (!c) return ''; const whisk = c.lower != null ? `` : ''; return `
covered ${whisk} ${p1(c.share)} ${esc(c.k)} of ${esc(c.n)} drawn sites

Covered: ${esc(c.what)}. ${esc(c.verdict)} (lower bound ${p1(c.lower)}, bar ${p1(c.bar)}). The shares below count covered sites only; a site that is not covered is neither a hit nor a miss.

`; } function singleTruth(st, s) { const o = st.single_truth; if (!o) return ''; const w = o.within_1; return `
Against the ${esc(s.truth ? s.truth.voxel_um : '')} µm scan alone: ${esc(o.verdict)}${w ? `, ${p1(w.share)} within 1 voxel (${esc(w.k)} of ${esc(w.n)}, ${VX_BASIS[w.basis] || w.basis}; lower bound ${p1(w.lower)})` : ''}

${esc(o.why)}${o.instrument_limited ? ' (limited by the instrument)' : ''}.

Controls against the one scan

${controls({ controls: o.controls })}
`; } function earlierTests(s) { if (!s.earlier || !s.earlier.length) return ''; return `
Earlier frozen test${s.earlier.length > 1 ? 's' : ''} on this scroll (spent)
`; } function hist(st, showPub) { const h = st.residual_hist, ph = st.published_hist; if (!h || !h.edges || h.edges.length < 2) return '

No residual distribution for this stratum.

'; const W = 360, H = 130, L = 8, B = 22, T = 10; const e = h.edges, lo = e[0], hi = e[e.length - 1]; const X = (v) => L + (W - 2 * L) * (v - lo) / (hi - lo); const all = [...h.counts, ...(showPub && ph && ph.counts ? ph.counts : [])]; const max = Math.max(1, ...all); const Y = (c) => H - B - (H - B - T) * c / max; let bars = ''; h.counts.forEach((c, i) => { if (!c) return; const x0 = X(e[i]) + 1, x1 = X(e[i + 1]) - 1; bars += `${e[i]} to ${e[i + 1]} voxels: ${c} sites`; }); let pub = ''; if (showPub && ph && ph.counts && ph.edges && ph.edges.length === ph.counts.length + 1) { let d = `M${X(ph.edges[0]).toFixed(1)},${Y(0).toFixed(1)}`; ph.counts.forEach((c, i) => { d += `L${X(ph.edges[i]).toFixed(1)},${Y(c).toFixed(1)}L${X(ph.edges[i + 1]).toFixed(1)},${Y(c).toFixed(1)}`; }); d += `L${X(ph.edges[ph.edges.length - 1]).toFixed(1)},${Y(0).toFixed(1)}`; pub = `published label`; } const ticks = [-4, -2, -1, 0, 1, 2, 4].filter((v) => v >= lo && v <= hi) .map((v) => `${v > 0 ? '+' + v : v}`).join(''); const out = (h.under || h.over) ? `${h.under} below ${lo}, ${h.over} above +${hi}` : ''; return ` within 1 voxel ${bars}${pub} ${ticks}${out}`; } function meter(s) { const v = s.vertices, by = v.by_code, tot = Math.max(1, v.released + v.held_back); const part = (n, color) => (n ? `` : ''); return `
${part(by['0'], 'var(--snap)')}${part(by['2'], 'var(--fill)')}${part(by['1'], 'var(--pub)')}${part(v.held_back, 'var(--held)')}
snapped ${p1(by['0'] / tot)}filled ${p1(by['2'] / tot)}left in place ${p1(by['1'] / tot)}held back ${p1(v.held_back / tot)}
`; } function chip(st, on, scroll) { const icon = VX_ICON[st.verdict] || ''; return ``; } function controls(st) { if (!st.controls || !st.controls.length) return ''; return ``; } function numbers(s) { const rows = []; for (const st of s.strata || []) { if (st.coverage) { const c = st.coverage; rows.push(`${esc(st.id)}${esc(c.verdict)}covered${esc(c.k)}${esc(c.n)}${p1(c.share)}${p1(c.lower)}${p1(c.upper)}drawn sites`); } if (st.single_truth && st.single_truth.within_1) { const w = st.single_truth.within_1; rows.push(`${esc(st.id)}, one scan${esc(st.single_truth.verdict)}1${esc(w.k)}${esc(w.n)}${p1(w.share)}${w.lower != null ? p1(w.lower) : ''}${w.upper != null ? p1(w.upper) : ''}${esc(w.basis)}`); } for (const t of VX_TOLS) { const w = st.within[t]; rows.push(`${esc(st.id)}${esc(st.verdict)}${t}${w ? w.k : ''}${w ? w.n : ''}${w ? p1(w.share) : 'not measured'}${w && w.lower != null ? p1(w.lower) : ''}${w && w.upper != null ? p1(w.upper) : ''}${w ? esc(w.basis) : ''}`); } } const v = s.vertices; return `
Show numbers

Vertices released ${fmt(v.released)} (code 0: ${fmt(v.by_code['0'])}, code 2: ${fmt(v.by_code['2'])}, code 1: ${fmt(v.by_code['1'])}), held back ${fmt(v.held_back)}. Label scan ${esc(s.label_scan.voxel_um)} µm${s.truth ? `; truth ${esc(s.truth.voxel_um)} µm scan` : ''}${s.second_truth ? `; second truth ${esc(s.second_truth.voxel_um)} µm scan` : ''}${s.oracle ? `; positive control ${esc(s.oracle.voxel_um)} µm scan` : ''}.${s.void && s.void.length ? ` Void: ${esc(s.void.join('; '))}.` : ''}

${rows.length ? `
${rows.join('')}
StratumVerdictVoxelsknShareLowerUpperBasis
` : ''} ${s.certificate ? `

Certificate: ${esc(s.certificate.method)}, lower bound ${p1(s.certificate.lower)} at ${p1(s.certificate.level)} over ${fmt(s.certificate.n)} vertices.

` : ''}
`; } // ---------------------------------------------------------------- cards function stratumOrder(strata) { const rank = { C0: 0, C0L: 1, C2: 2, C1: 3 }; return strata.slice().sort((a, b) => (rank[a.id] ?? 9) - (rank[b.id] ?? 9)); } function strataBody(s, rule) { const strata = stratumOrder(s.strata || []); const prim = strata.find((x) => x.primary) || strata[0]; const cur = strata.find((x) => x.id === VX.pick[s.scroll]) || prim; const one = prim && prim.within['1']; const pubc = prim && (prim.controls || []).find((c) => /^published/.test(c.name)); const cov = prim && prim.coverage; const head2 = one ? `${cov ? `

The two scans agree on the face at ${p1(cov.share)} of drawn sites (${esc(cov.k)} of ${esc(cov.n)}). On those, ${p1(one.share)} of snapped vertices lie within 1 voxel (${esc(prim.id)}, ${esc(prim.verdict)}). One-sided 95% lower bounds ${p1(cov.lower)} (bar ${p1(cov.bar)}) and ${p1(one.lower)} (bar ${p1(rule.bar)}).

` : `

${p1(one.share)} within 1 voxel (${esc(prim.id)}, ${esc(prim.verdict)}). One-sided 95% lower bound ${p1(one.lower)} (bar ${p1(rule.bar)}).

`} ${s.scope ? `

${esc(s.scope)}

` : ''}

${pubc ? `${esc(pubc.name.replace(/^published label/, 'Published label'))}: ${p1(pubc.observed)}.` : ''}${s.void && s.void.length ? ` The test is void: ${esc(s.void.join('; '))}.` : ''}

` : ''; const pubOn = !!VX.pick[`${s.scroll}:pub`]; return `${head2} ${meter(s)}
${strata.map((x) => chip(x, x.id === cur.id, s.scroll)).join('')}

${esc(cur.id)}: share within each tolerance

${coverageBar(cur)}${tolBars(cur, rule)}

${esc(cur.verdict)}: ${esc(cur.why)}${cur.instrument_limited ? ' (limited by the instrument)' : ''}. ${esc(cur.n_selected)} sites selected${cur.coverage ? `, ${esc(cur.coverage.k)} covered` : `, ${esc(cur.n_scorable)} scorable`}. Whiskers: one-sided 95% interval. Dashed line: the bar.

${esc(cur.id)}: signed residual, voxels

${hist(cur, pubOn)}

${esc(cur.residual_hist && cur.residual_hist.sign ? cur.residual_hist.sign : '')}. Shaded: within 1 voxel.${cur.median_abs != null ? ` Median distance ${cur.median_abs.toFixed(2)} voxels.` : ''}

Controls (each must be able to fail)

${controls(cur)} ${singleTruth(cur, s)}

What this does not show: labels that follow the wrong wrap, sheets that touch with no gap, and any scroll, segment or region not scored here${cur.coverage ? ', and any site the two scans do not cover' : ''}.

${earlierTests(s)} ${numbers(s)}`; } function scrollCard(s) { const rule = VX.doc.rule || {}; const twoScan = (s.strata || []).some((x) => x.coverage); const badge = { measured: twoScan ? 'Model output, measured where two finer scans agree' : 'Model output, measured against an independent finer scan', certified: 'Model output, truth-free certificate', not_shown: (s.strata || []).length ? 'tested; no claim' : 'no claim' }[s.claim]; const head = `

${esc(s.scroll)}

label scan ${esc(s.label_scan.voxel_um)} µm voxels${s.truth ? `, truth from a ${esc(s.truth.voxel_um)} µm scan` : ''}${s.second_truth ? ` and a ${esc(s.second_truth.voxel_um)} µm scan` : ''}
${VX_CLAIMS[s.claim]} ${badge}
`; if (s.claim === 'not_shown') { const tested = (s.strata || []).length > 0; return `
${head}

Not shown: ${esc(s.why_not_shown)}.${tested ? ' The numbers below are what the test measured (model output); they make no claim.' : ''}

${tested ? strataBody(s, rule) : `${meter(s)}${numbers(s)}`}
`; } if (s.claim === 'certified') { const c = s.certificate; return `
${head}

One-sided ${p1(c.level)} lower bound ${p1(c.lower)} within 1 voxel (bar ${p1(rule.bar)}).

No truth scan; lower bound from the certificate, over ${fmt(c.n)} vertices. It rests on these assumptions:

${meter(s)}${numbers(s)}
`; } return `
${head}${strataBody(s, rule)}
`; } function renderCards() { const d = VX.doc; const sc = d.scrolls.slice().sort((a, b) => VX_ORDER[a.claim] - VX_ORDER[b.claim]); const count = (c) => d.scrolls.filter((s) => s.claim === c).length; $('vx-tiles').innerHTML = ['measured', 'certified', 'not_shown'].map((c) => `
${count(c)}scrolls ${VX_CLAIMS[c].toLowerCase()}
`).join(''); $('vx-cards').innerHTML = sc.map(scrollCard).join(''); $('vx-cards').querySelectorAll('.vx-chip').forEach((b) => { b.onclick = () => { VX.pick[b.dataset.scroll] = b.dataset.stratum; renderCards(); }; }); $('vx-cards').querySelectorAll('input[data-pub]').forEach((c) => { c.onchange = () => { VX.pick[`${c.dataset.pub}:pub`] = c.checked; renderCards(); }; }); const pre = d.prereg || {}; $('vx-prereg').textContent = `${pre.sha256 || 'n/a'}, frozen ${pre.frozen || 'n/a'}`; const pr = d.prizes_read || {}; $('vx-elig').innerHTML = d.fixture ? 'The fixture\'s scrolls are made up.' : `Sourced fact: none of these scrolls is on the prize lists at scrollprize.org/prizes (read ${esc(pr.date)}).`; $('vx-src').textContent = `${d.dataset.repo} ${d.dataset.release} at ${d.dataset.revision.slice(0, 12)}, summary ${d.generated}${d.fixture ? ', synthetic fixture' : ''}`; } // ---------------------------------------------------------------- showcase: residual heatmap and CT with the truth face const RS = 12; // floats per showcase line piece: published, snapped, truth (ax ay bx by each) async function openShowcase(segment) { const list = (VX.doc && VX.doc.showcase) || []; const e = list.find((x) => x.segment === segment) || list[0]; if (!e) throw new Error('no showcase segment'); const base = new URL(e.file, VX.url).href; const meta = await getJSON(base); // the grids are plain number lists (null: no value) const res = Float32Array.from(meta.residual, (v) => (v == null ? NaN : v)), state = Uint8Array.from(meta.state); const xyz = Float32Array.from(meta.xyz), rows = Float32Array.from(meta.rows); VX.show = { meta, res, state, xyz, rows, plane: 0, cx: 0, cy: 0, win: Number($('vx-win').value) || 192, ct: null, mode: (document.querySelector('input[name="vx-mode"]:checked') || {}).value || 'signed' }; $('vx-show-title').textContent = `${meta.scroll} · ${meta.segment}`; $('vx-truth-note').textContent = meta.truth_note; const mid = Math.floor(meta.planes.length / 2); pickPlane(mid); heat(); await showDraw(); } function pickPlane(i) { // center on a piece a quarter of the way along the plane's line const V = VX.show, p = V.meta.planes[i]; V.plane = i; if (!p || !p.count) return; const q = RS * (p.first + Math.floor(p.count / 4)); V.cx = V.rows[q + 4]; V.cy = V.rows[q + 5]; } function divColor(v, css) { // diverging: blue (negative) to a neutral gray to orange (positive), clamped at +-2 voxels const t = Math.max(-1, Math.min(1, v / 2)); const hex = (s) => { const m = s.trim().replace('#', ''); return [0, 2, 4].map((i) => parseInt(m.slice(i, i + 2), 16)); }; const neg = hex(css.getPropertyValue('--neg') || '#2f7bf6'), pos = hex(css.getPropertyValue('--pos') || '#e0701a'), mid = hex(css.getPropertyValue('--neutral') || '#c9ccd6'); const a = t < 0 ? neg : pos, k = Math.abs(t); return `rgb(${mid.map((m, i) => Math.round(m + (a[i] - m) * k)).join(',')})`; } function heat() { const V = VX.show; if (!V) return; const [h, w] = V.meta.shape, cv2 = $('vx-heat'), g = cv2.getContext('2d'); const cw = Math.max(2, Math.floor(Math.min(900, cv2.parentNode.clientWidth || 600) / w)); cv2.width = w * cw; cv2.height = h * cw; const css = getComputedStyle(document.documentElement); const surf = css.getPropertyValue('--panel').trim() || '#fff', line = css.getPropertyValue('--line').trim() || '#ccc'; const tol = V.mode === 'signed' ? null : Number(V.mode); g.fillStyle = surf; g.fillRect(0, 0, cv2.width, cv2.height); for (let i = 0; i < h; i++) for (let j = 0; j < w; j++) { const k = i * w + j, s = V.state[k], x = j * cw, y = i * cw; if (s === 2) { g.fillStyle = css.getPropertyValue('--heldcell').trim() || '#ddd'; g.fillRect(x, y, cw, cw); continue; } // held back: never drawn if (s === 1 || !Number.isFinite(V.res[k])) { // no value: hatched g.strokeStyle = line; g.lineWidth = 1; g.beginPath(); g.moveTo(x, y + cw); g.lineTo(x + cw, y); g.stroke(); continue; } const v = V.res[k]; g.fillStyle = tol == null ? divColor(v, css) : (Math.abs(v) <= tol ? css.getPropertyValue('--snap').trim() : css.getPropertyValue('--pub').trim()); g.fillRect(x, y, cw, cw); } const p = V.meta.planes[V.plane]; if (p) { const i = V.meta.planes.indexOf(p); g.strokeStyle = css.getPropertyValue('--ink').trim(); g.lineWidth = 2; g.strokeRect(1, i * cw + 1, cv2.width - 2, cw - 2); } V.cw = cw; $('vx-heat-legend').innerHTML = tol == null ? `-20+2 voxels (clamped)no valueheld back for evaluation` : `within ${tol} voxel${tol === 1 ? '' : 's'}not withinno valueheld back for evaluation`; } async function showDraw() { const V = VX.show; if (!V) return; const cvs = $('vx-cv'), g = cvs.getContext('2d'), W = cvs.width, n = V.win, k = W / n; const p = V.meta.planes[V.plane], z = p ? p.z : 0; const x0 = Math.round(V.cx - n / 2), y0 = Math.round(V.cy - n / 2); $('vx-z').textContent = `z ${z}`; if (V.meta.volume) { const key = `${z}|${y0}|${x0}|${n}`; if (!V.ct || V.ct.key !== key) { const buf = await ctWindow(V.meta.volume, z, y0, x0, n); const img = new ImageData(n, n); for (let i = 0; i < n * n; i++) { img.data[4 * i] = img.data[4 * i + 1] = img.data[4 * i + 2] = buf[i]; img.data[4 * i + 3] = 255; } const off = document.createElement('canvas'); off.width = off.height = n; off.getContext('2d').putImageData(img, 0, 0); V.ct = { key, img: off }; } g.imageSmoothingEnabled = false; g.drawImage(V.ct.img, 0, 0, W, W); } else { g.fillStyle = '#15171f'; g.fillRect(0, 0, W, W); g.fillStyle = 'rgba(255,255,255,.55)'; g.font = '14px system-ui, sans-serif'; g.fillText('Synthetic fixture: no CT', 14, 24); } const X = (x) => (x - x0 + 0.5) * k, Y = (y) => (y - y0 + 0.5) * k; const css = getComputedStyle(document.documentElement); const piece = (o, color, width, dash) => { g.strokeStyle = color; g.lineWidth = width; g.setLineDash(dash || []); g.lineCap = 'round'; g.beginPath(); for (let q = p.first; q < p.first + p.count; q++) { const a = RS * q + o; g.moveTo(X(V.rows[a]), Y(V.rows[a + 1])); g.lineTo(X(V.rows[a + 2]), Y(V.rows[a + 3])); } g.stroke(); g.setLineDash([]); }; if (p && p.count && !V.meta.volume) { // no CT in the fixture: a made-up sheet, drawn as a band along the made-up face piece(8, css.getPropertyValue('--band').trim() || '#d9c6a3', 7 * k); } if (p && p.count) { if ($('vx-l-pub').checked) piece(0, css.getPropertyValue('--pub').trim(), 2.5); if ($('vx-l-snap').checked) piece(4, css.getPropertyValue('--snap').trim(), 2.5); if ($('vx-l-truth').checked) { piece(8, '#11131c', 4.5, [7, 5]); piece(8, '#ffffff', 2, [7, 5]); } } g.fillStyle = '#fff'; g.fillRect(16, W - 22, 10 * k, 4); g.font = '13px system-ui, sans-serif'; g.fillText(V.meta.voxel_um ? `10 voxels (${Math.round(10 * V.meta.voxel_um)} µm)` : '10 voxels', 16, W - 30); } function heatCell(ev) { const V = VX.show; if (!V) return null; const b = $('vx-heat').getBoundingClientRect(), [h, w] = V.meta.shape; const j = Math.floor((ev.clientX - b.left) / b.width * w), i = Math.floor((ev.clientY - b.top) / b.height * h); if (i < 0 || j < 0 || i >= h || j >= w) return null; return { i, j, k: i * w + j }; } // ---------------------------------------------------------------- wiring function wireShowcase() { const heatCv = $('vx-heat'), tip = $('vx-tip'); heatCv.addEventListener('mousemove', (ev) => { const c = heatCell(ev), V = VX.show; if (!c) { tip.hidden = true; return; } const s = V.state[c.k], v = V.res[c.k]; tip.textContent = s === 2 ? 'held back for evaluation' : (s === 1 || !Number.isFinite(v)) ? 'no value here' : `${sgn(v)} voxels (row ${c.i}, column ${c.j})`; tip.hidden = false; tip.style.left = `${ev.offsetX + 14}px`; tip.style.top = `${ev.offsetY + 10}px`; }); heatCv.addEventListener('mouseleave', () => { tip.hidden = true; }); heatCv.addEventListener('click', (ev) => { const c = heatCell(ev), V = VX.show; if (!c || V.state[c.k] === 2) return; const x = V.xyz[3 * c.k], y = V.xyz[3 * c.k + 1], z = V.xyz[3 * c.k + 2]; let best = Infinity, bi = 0; V.meta.planes.forEach((p, i) => { const d = Math.abs(p.z - z); if (d < best) { best = d; bi = i; } }); V.plane = bi; V.cx = x; V.cy = y; heat(); showDraw(); }); document.querySelectorAll('input[name="vx-mode"]').forEach((r) => { r.onchange = () => { VX.show.mode = r.value; heat(); }; }); ['vx-l-pub', 'vx-l-snap', 'vx-l-truth'].forEach((id) => { $(id).onchange = () => showDraw(); }); $('vx-win').onchange = () => { VX.show.win = Number($('vx-win').value); showDraw(); }; window.addEventListener('resize', () => heat()); } async function vxInit() { VX.url = vxURL(); let d; try { const r = await fetch(VX.url, { credentials: 'omit' }); if (!r.ok) { if (params.get('vx')) throw new Error(`${r.status} ${VX.url}`); return; } // no results yet: the tab stays hidden d = await r.json(); } catch (e) { if (!params.get('vx')) return; $('vx-tabbtn').hidden = false; $('vx-error').hidden = false; $('vx-error').textContent = `Could not load the voxel-exact summary: ${e.message}`; return; } const bad = vxValid(d); if (bad.length) { if (!params.get('vx')) return; $('vx-tabbtn').hidden = false; $('vx-error').hidden = false; $('vx-error').textContent = `The voxel-exact summary does not validate: ${bad.slice(0, 3).join('; ')}`; return; } VX.doc = d; VX.fixture = d.fixture === true; $('vx-tabbtn').hidden = false; // a summary from ?vx=URL is someone else's file: say so, so a shared link cannot pass as this Space's results if (params.get('vx') && params.get('vx') !== 'fixture') { $('vx-error').hidden = false; $('vx-error').textContent = `Loaded from ${VX.url} (the vx parameter), not this Space's own results.`; } document.querySelectorAll('.vx-fixture').forEach((b) => { b.hidden = !VX.fixture; }); document.body.classList.toggle('vx-fx', VX.fixture); renderCards(); if (typeof table === 'function') table(); const sc = d.showcase || []; $('vx-show-none').hidden = sc.length > 0; $('vx-show').hidden = !sc.length; if (sc.length) { $('vx-show-pick').innerHTML = sc.map((s) => ``).join(''); $('vx-show-pick').onchange = () => openShowcase($('vx-show-pick').value).catch((e) => { $('vx-show-title').textContent = e.message; }); wireShowcase(); await openShowcase(sc[0].segment).catch((e) => { $('vx-show-title').textContent = e.message; }); } if (params.get('tab') === 'exact') tab('exact'); } // the scroll's claim level for the All segments table (app.js) window.vxClaim = (scroll) => { if (!VX.doc) return null; const s = VX.doc.scrolls.find((x) => x.scroll === scroll); return s ? VX_CLAIMS[s.claim] : 'Not scored'; }; Object.assign(window.snappedLabels, { voxelExact: () => (VX.doc ? JSON.parse(JSON.stringify(VX.doc)) : null), openShowcase: (segment) => openShowcase(segment), }); window.vxReady = vxInit();