File size: 38,650 Bytes
d3de41b
b2fee12
 
 
 
 
 
 
3ba468f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b2fee12
 
dd7161c
b2fee12
 
 
 
 
 
 
 
dd7161c
b2fee12
 
 
 
 
 
d521248
538ab06
b2fee12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd7161c
b2fee12
 
 
 
 
 
 
 
 
 
 
3ba468f
b2fee12
 
 
 
 
 
dd7161c
b2fee12
 
 
dd7161c
 
 
 
 
538ab06
dd7161c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
538ab06
 
dd7161c
 
 
538ab06
dd7161c
 
 
 
 
538ab06
dd7161c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b2fee12
 
 
3ba468f
b2fee12
 
 
 
 
 
 
 
d521248
 
 
 
b2fee12
 
 
3ba468f
3e65159
b2fee12
 
 
3ba468f
b2fee12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd7161c
b2fee12
d3de41b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Snapped Labels</title>
<meta name="description" content="Published Vesuvius Challenge surface labels moved onto the papyrus surface, shown on live X-ray CT.">
<link rel="stylesheet" href="style.css">
<!-- space-onescroll:start -->
<!-- one page scroll bar: written by python -m kit spaceconnect render; do not edit -->
<style>iframe[srcdoc]{display:block;max-height:none!important}</style>
<script>
(function () {
  if (window.__oneScroll) return;
  window.__oneScroll = true;
  var CSS = 'html,body{height:auto!important;min-height:0!important}html{overflow:hidden!important}';
  function size(f) {
    var d, st = f.__os;
    try { d = f.contentDocument; } catch (e) { return; }
    if (!d || !d.body || st.off) return;
    var de = d.documentElement, r = Math.ceil(de.getBoundingClientRect().height), over = de.scrollHeight;
    var ch = f.clientHeight, t = r;
    if (over > ch + 1) t = Math.max(r, over);
    else if (r >= st.r) t = Math.max(r, ch);
    st.r = r;
    if (Math.abs(t - ch) < 2) return;
    var now = Date.now();
    st.n = now - st.t0 < 4000 ? st.n + 1 : 1;
    if (st.n === 1) st.t0 = now;
    if (st.n > 40) { st.off = true; f.removeAttribute('scrolling'); var g = d.getElementById('space-onescroll'); if (g) g.remove(); return; }
    f.style.setProperty('height', t + 'px', 'important');
  }
  function attach(f) {
    var d, st = f.__os;
    try { d = f.contentDocument; } catch (e) { return; }
    if (!d || !d.documentElement || st.doc === d) return;
    st.doc = d; st.r = Infinity; st.n = 0; st.off = false;
    if (!d.getElementById('space-onescroll')) {
      var s = d.createElement('style'); s.id = 'space-onescroll'; s.textContent = CSS;
      (d.head || d.documentElement).appendChild(s);
    }
    f.setAttribute('scrolling', 'no');
    f.style.setProperty('min-height', '0', 'important');
    f.style.setProperty('max-height', 'none', 'important');
    var w = d.defaultView, go = function () { size(f); };
    if (w && w.ResizeObserver) { var ro = new w.ResizeObserver(go); ro.observe(d.documentElement); if (d.body) ro.observe(d.body); }
    d.addEventListener('load', go, true);
    go();
  }
  function bind(f) {
    if (f.__os || f.getAttribute('data-scroll') === 'inner') return;
    try { if (!f.contentDocument) return; } catch (e) { return; }
    f.__os = {t0: 0, n: 0, r: 0};
    f.addEventListener('load', function () { attach(f); });
    if (f.contentDocument.readyState !== 'loading') attach(f);
    else f.contentDocument.addEventListener('DOMContentLoaded', function () { attach(f); });
  }
  function scan() { var fs = document.getElementsByTagName('iframe'); for (var i = 0; i < fs.length; i++) bind(fs[i]); }
  function start() {
    scan();
    new MutationObserver(scan).observe(document.documentElement, {childList: true, subtree: true});
    window.addEventListener('resize', function () {
      var fs = document.getElementsByTagName('iframe');
      for (var i = 0; i < fs.length; i++) if (fs[i].__os) size(fs[i]);
    });
  }
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start); else start();
})();
</script>
<!-- space-onescroll:end -->
</head>
<body>
<div class="vx-fixture vx-banner" role="alert" hidden><b>Synthetic fixture.</b> Every number, scroll and line in the Voxel exact tab is made up, to test the page. No real results are shown.</div>
<header class="top">
  <div class="brand">
    <h1>Snapped Labels</h1>
    <p class="sub">Published surface labels of four Herculaneum scrolls, moved along their normals onto the papyrus surface in the CT. Orange is the published label, blue is where it lands.</p>
  </div>
  <nav class="tabs" role="tablist">
    <button data-tab="view" role="tab" aria-selected="true">Viewer</button>
    <button data-tab="all" role="tab">All segments</button>
    <button data-tab="exact" role="tab" id="vx-tabbtn" hidden>Voxel exact</button>
    <button data-tab="how" role="tab">How it works</button>
    <button data-tab="connect" role="tab">Connect your tool</button>
  </nav>
</header>

<section class="stats" aria-label="Measured accuracy">
  <div class="stat"><b>+2.15 voxels</b><span>closer to the recto face than the published labels on 71 fresh PHerc0814 and PHerc0841 test sites, with the single-scan snap. Seven community snaps, run on the same sites: +0.26 at most.</span></div>
  <div class="stat"><b>91%</b><span>of scorable vertices within 1 voxel of the recto face in a 1.129 µm scan, on 60 fresh PHerc0139 test sites (sites it could not score left out). Published labels: 24%.</span></div>
  <div class="stat"><b>71%</b><span>within 1 voxel on 60 fresh PHerc0814 test sites with the single-scan snap. Published labels: 24%.</span></div>
  <div class="stat"><b>+0.61 voxels</b><span>closer to the surface: a 3D surface model trained on snapped labels against the same model trained on published ones, scored on a scroll neither saw.</span></div>
  <div class="stat"><b id="st-count">108</b><span>segments on PHerc0139, PHerc0814, PHerc0841 and PHerc0172, as tifxyz meshes you can drop into VC3D or villa.</span></div>
</section>

<main>
<section data-pane="view" class="viewer">
  <aside class="side">
    <label class="lbl" for="f-scroll">Scroll</label>
    <select id="f-scroll"></select>
    <label class="lbl" for="f-find">Segment</label>
    <input id="f-find" type="search" placeholder="filter, e.g. w025" autocomplete="off">
    <ul id="seg-list" class="seglist" aria-label="Segments"></ul>
  </aside>
  <div class="stage">
    <div class="bar">
      <span id="v-title" class="vt">Loading…</span>
      <span class="sp"></span>
      <label class="tog"><input type="checkbox" id="l-pub" checked><i class="dot pub"></i>Published</label>
      <label class="tog"><input type="checkbox" id="l-snap" checked><i class="dot snap"></i>Snapped</label>
      <label class="tog"><input type="checkbox" id="l-move" checked><i class="dot move"></i>Moves</label>
      <button id="b-anim" class="anim" type="button" aria-pressed="false" title="Move each vertex from its published position to its snapped one, slowly, on a loop">Animate snap</button>
    </div>
    <div class="canvaswrap">
      <canvas id="cv" width="720" height="720" aria-label="CT slice with the published and snapped labels"></canvas>
      <div id="cv-msg" class="cvmsg" hidden></div>
    </div>
    <div class="ctl">
      <button id="b-prev" title="Previous stretch of the label (left arrow)">◀</button>
      <button id="b-next" title="Next stretch of the label (right arrow)">▶</button>
      <label class="zl">z <input id="z-range" type="range" min="0" max="0" value="0"> <output id="z-out">0</output></label>
      <label class="zl">Window <select id="win"><option value="96">96 voxels</option><option value="192" selected>192 voxels</option><option value="384">384 voxels</option></select></label>
    </div>
    <p class="hint">Click the image to center it. The lines are where each mesh crosses this z plane: orange for the published label, blue for the snapped one, with gray strokes joining matching points. The blue line moves only vertices whose own face was measured (<code>abstain.tif</code> 0). Filled vertices (<code>abstain.tif</code> 2, moved in the dataset by their measured neighbors' offsets) and vertices left in place (1) are drawn at the published position, so the two lines coincide there.</p>
    <div id="seg-card" class="card"></div>
  </div>
</section>

<section data-pane="all" hidden>
  <div class="tablewrap"><table id="tbl"><thead><tr>
    <th>Scroll</th><th>Segment</th><th>Method</th><th class="n">Vertices</th><th class="n">Snapped</th><th class="n">Median move</th><th class="n">Held back</th><th id="th-claim" hidden>Claim</th>
  </tr></thead><tbody></tbody></table></div>
</section>

<section data-pane="exact" hidden class="vx">
  <div class="vx-fixture vx-banner inline" hidden><b>Synthetic fixture.</b> The scrolls SYNTH-A, SYNTH-B and SYNTH-C and every number below are made up, to test the page.</div>
  <p id="vx-error" class="vx-error" hidden></p>
  <div class="vx-intro">
    <h2>Is each snapped vertex within one voxel of the papyrus face?</h2>
    <p>Per scroll, one of three claim levels. <b>Measured</b>: scored against the face seen in an independent, finer scan of the same scroll, and at least one class cleared the bar. Where a card says <i>covered</i>, the claim holds only on the share of sites where two finer scans agree on the face; that share is shown beside it, and the card says in words what exact means there. <b>Certified</b>: no finer scan, so a lower bound from a truth-free certificate whose assumptions are listed. <b>Not shown</b>: neither holds, and the card says why; where a test ran, the card still shows what it measured, which makes no claim. Every number here is model output: the snapped meshes come from a band finder, and the truth face is itself found by a rule.</p>
  </div>
  <section class="stats vx-tiles" id="vx-tiles" aria-label="Scrolls by claim level"></section>
  <div id="vx-cards" class="vx-cards"></div>

  <section class="vx-showwrap" aria-labelledby="vx-show-h">
    <h2 id="vx-show-h">Per-vertex residuals</h2>
    <p id="vx-show-none" class="hint">No public residual view yet. Drawing the truth face at every vertex would publish where the face is, densely, and spend that region for every later test, so a region appears here only once it is named as spent.</p>
    <div id="vx-show" hidden>
      <div class="bar">
        <select id="vx-show-pick" aria-label="Showcase segment"></select>
        <span id="vx-show-title" class="vt"></span>
        <span class="sp"></span>
        <fieldset class="vx-modes"><legend class="lbl">Color</legend>
          <label><input type="radio" name="vx-mode" value="signed" checked> signed residual</label>
          <label><input type="radio" name="vx-mode" value="0.5"> within 0.5</label>
          <label><input type="radio" name="vx-mode" value="1"> within 1</label>
          <label><input type="radio" name="vx-mode" value="2"> within 2</label>
        </fieldset>
      </div>
      <div class="vx-showgrid">
        <div class="vx-heatwrap">
          <canvas id="vx-heat" width="600" height="150" aria-label="Signed residual at each vertex of the label surface, rows by columns; click a cell to see it on the CT"></canvas>
          <div id="vx-tip" class="vx-tip" hidden></div>
          <div id="vx-heat-legend" class="legend vx-heatlegend"></div>
          <p class="hint">Each cell is a vertex of the label surface (grid rows and columns). Blue: the snapped point lies inward of the truth face; orange: outward. Click a cell to center the CT on it. The outlined row is the z plane shown.</p>
        </div>
        <div>
          <div class="bar">
            <label class="tog"><input type="checkbox" id="vx-l-pub" checked><i class="dot pub"></i>Published</label>
            <label class="tog"><input type="checkbox" id="vx-l-snap" checked><i class="dot snap"></i>Snapped</label>
            <label class="tog"><input type="checkbox" id="vx-l-truth" checked><i class="dot truth"></i>Truth face</label>
            <span class="sp"></span><span id="vx-z" class="hint"></span>
            <select id="vx-win" aria-label="Window"><option value="96">96 voxels</option><option value="192" selected>192 voxels</option><option value="384">384 voxels</option></select>
          </div>
          <div class="canvaswrap"><canvas id="vx-cv" width="576" height="576" aria-label="CT slice with the published, snapped and truth lines"></canvas></div>
          <p id="vx-truth-note" class="hint"></p>
        </div>
      </div>
    </div>
  </section>

  <section class="prose vx-how">
    <h2>How it is measured</h2>
    <figure class="fig">
      <svg class="vx-diagram" viewBox="0 0 680 312" role="img" aria-labelledby="vx-d1t vx-d1d">
        <title id="vx-d1t">A cross section through two wraps of papyrus</title>
        <desc id="vx-d1d">The published label sits beside the sheet. The snap moves it along the mesh normal, toward the scroll's center line side, onto the sheet's recto face. The truth face, found in a finer scan, is drawn dashed, with a band of one label voxel on each side. The verso face, on the far side of the sheet, is a control.</desc>
        <defs><marker id="vx-ah" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0L10,5L0,10z" fill="currentColor"/></marker></defs>
        <path class="d-band" d="M262,20 C250,110 250,190 262,280 L318,280 C306,190 306,110 318,20 Z"/>
        <path class="d-band" d="M622,20 C610,110 610,190 622,280 L672,280 C660,190 660,110 672,20 Z"/>
        <rect class="d-tol" x="241" y="20" width="26" height="260" rx="3"/>
        <path class="d-truth" d="M256,20 C244,110 244,190 256,280"/>
        <path class="d-recto" d="M262,20 C250,110 250,190 262,280"/>
        <path class="d-verso" d="M318,20 C306,110 306,190 318,280"/>
        <line class="d-arrow" x1="72" y1="150" x2="22" y2="150" marker-end="url(#vx-ah)"/>
        <text x="22" y="132" class="d-t">toward the scroll's</text><text x="22" y="176" class="d-t">center line</text>
        <line class="d-normal" x1="196" y1="150" x2="245" y2="150" marker-end="url(#vx-ah)"/>
        <circle class="d-pub" cx="190" cy="150" r="7"/>
        <circle class="d-snap" cx="253" cy="150" r="7"/>
        <text x="190" y="128" class="d-t" text-anchor="middle">published</text>
        <text x="212" y="172" class="d-t muted" text-anchor="middle">normal</text>
        <line class="d-lead" x1="250" y1="160" x2="200" y2="236"/>
        <text x="200" y="252" class="d-t" text-anchor="middle">snapped, on the recto face</text>
        <line class="d-lead" x1="248" y1="62" x2="352" y2="56"/>
        <text x="358" y="52" class="d-t">truth face (dashed), from the finer scan</text>
        <text x="358" y="70" class="d-t muted">shaded: ±1 label voxel around it</text>
        <line class="d-lead" x1="312" y1="208" x2="352" y2="208"/>
        <text x="358" y="212" class="d-t">verso face: a control</text>
        <text x="642" y="306" class="d-t muted" text-anchor="middle">next wrap</text>
        <text x="290" y="306" class="d-t muted" text-anchor="middle">one wrap of papyrus</text>
        <text x="8" y="306" class="d-t muted">not to scale</text>
      </svg>
      <figcaption>One vertex, seen in cross section: published (orange), snapped along its normal onto the recto face (blue), and the truth face (dashed) with its one-voxel band. Not to scale; a label voxel is about 8 to 9 µm.</figcaption>
    </figure>
    <ol class="vx-flow" aria-label="How a test runs, in order">
      <li><b>Release 1.0.1</b>, pinned by its revision, so the vertices scored are the ones you download.</li>
      <li><b>Split by <code>abstain.tif</code></b>: C0 snapped, C2 filled, C1 left in place. Each is scored on its own.</li>
      <li><b>Test sites</b> drawn after the rule was frozen, in regions never used before.</li>
      <li><b>Truth face</b> found in the finer scan (1.129 µm for PHerc0139); a 2.4 µm scan, where one exists, is the positive control. In a two-scan test a second finer scan (2.403 µm for PHerc0139) reads the face too, and a site counts only where the two agree within 1 voxel (covered); the claim is then on covered sites, with the covered share and its own bar beside it.</li>
      <li><b>Negative controls</b>: the published label, offsets of 1.5 and 3 voxels planted on purpose, and the verso face; in a two-scan test also the second scan moved by 1.5 and 3 voxels, and the snapped offsets scored against other sites' faces. Each must fail the bar.</li>
      <li><b>Verdict</b> per stratum: PASS, FAIL, NOT SHOWN or UNANSWERABLE; or VOID for the whole test when a control or the integrity check breaks.</li>
    </ol>
    <h2>The three claim levels</h2>
    <p><b>Measured.</b> A finer scan of the same scroll exists. At test sites drawn after the rule was fixed, the face is found in it, registered into the label scan, and each snapped vertex's distance to it is measured along the normal. The share within 1 voxel and its one-sided 95% lower bound are reported; the claim holds when the bound clears the bar. In a two-scan test the share counts covered sites only (where both finer scans name the face and agree within 1 voxel), so two numbers always go together: how many drawn sites are covered, and how many snapped vertices on those lie within 1 voxel. The rule was fixed before any test site was looked at; its preregistration digest is <code id="vx-prereg"></code>.</p>
    <p><b>Certified.</b> No finer scan. A certificate computed from the label scan alone gives a lower bound on the share within 1 voxel, valid only under the assumptions the card lists. It was fixed before any test site was looked at too, under the same preregistration.</p>
    <p><b>Not shown.</b> Neither a measurement nor a certificate holds for that scroll, or a control failed. The card says why. Where a test ran, the card still shows its shares, intervals and controls, so you can see how far it is from the bar; nothing on it is a claim.</p>
    <h2>Limits</h2>
    <ul>
      <li>A snap moves along the normal only. It cannot fix a label that follows the wrong wrap, and where two sheets touch the face it finds can belong to the neighbor.</li>
      <li>Only scored strata carry a claim, and a share is a share of test sites, not of every vertex. A covered claim says nothing about the sites the two scans do not cover, and agreement of two scans cannot see an error both share.</li>
      <li>The truth face is itself found by a rule on the finer scan, so it is model output too.</li>
      <li>A certificate rests on its stated assumptions. The certificate code and the snapping code are not public.</li>
      <li>Only the scrolls in the dataset appear here. The meshes are geometry: they say nothing about ink or text.</li>
    </ul>
    <h2>What each number is</h2>
    <div class="vx-tw"><table class="vx-labels"><thead><tr><th>On this tab</th><th>Claim label</th></tr></thead><tbody>
      <tr><td>Shares, bounds, histograms</td><td>Model output, measured</td></tr>
      <tr><td>A certificate's bound</td><td>Model output, certified</td></tr>
      <tr><td>Snapped and truth lines</td><td>Model output</td></tr>
      <tr><td>Which scrolls are prize-eligible</td><td id="vx-elig">Sourced fact</td></tr>
    </tbody></table></div>
    <p class="hint">Source: <span id="vx-src"></span>.</p>
    <p class="credit">Scans and source meshes: Vesuvius Challenge open data, CC BY-NC 4.0; the snapped meshes are shared under the same terms. Page code Apache 2.0. Made by Chase Hendrick.</p>
  </section>
</section>

<section data-pane="how" hidden class="prose">
  <figure class="fig"><img src="https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels/resolve/main/snapped-0139.gif" width="600" height="600" alt="PHerc0139 segment w054 on CT at z 8048: the published label, then the snapped label, then both with the moves, at four stops along the label" loading="lazy"><figcaption>PHerc0139 w054, z 8048: published (orange), snapped (blue), both.</figcaption></figure>
  <h2>What a snap does</h2>
  <p>A surface label is a mesh (tifxyz: three float grids, x, y and z in scan voxels) that follows one wrap of papyrus. Traced labels sit near the sheet but rarely on it: on fresh test sites only about a quarter of published label vertices were within one voxel of the sheet's recto face. A snap moves each vertex along its mesh normal onto the face of the bright band nearest it, on the side toward the scroll's center line.</p>
  <h2>Two methods</h2>
  <ul>
    <li><b>finesnap</b> (PHerc0139, PHerc0814, PHerc0841): the label's own 9.4 µm scan is registered, vertex by vertex, to a 2.4 µm scan of the same scroll, and the face is found there. Where that fails, the label scan's own face is used (<code>source.tif</code> says which).</li>
    <li><b>labelsnap</b> (PHerc0172): the face is found in the label's own 7.9 µm scan.</li>
  </ul>
  <h2>How it was measured</h2>
  <figure class="fig"><img src="https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels/resolve/main/accuracy.png" width="1920" height="576" alt="Bar chart: vertices within 1 voxel of the recto face. PHerc0139: published 23.7%, labelsnap 79.4%, finesnap 91.2%. PHerc0814: published 24.2%, labelsnap 71.0%." loading="lazy"></figure>
  <p>Truth is the recto face seen in an independent 1.129 µm scan, at test sites drawn after the method was fixed and never used before. PHerc0139, 60 sites: within 1 voxel 23.7% for the published labels, 79.4% for labelsnap, 91.2% for finesnap. PHerc0814, 60 sites: 24.2% for published labels, 71.0% for labelsnap. A 3D surface model trained on snapped PHerc0139 labels placed the surface 0.61 voxels closer on PHerc0814 than the same model trained on published labels (95% interval 0.39 to 0.84; all 9 seed pairings).</p>
  <h2>Against seven community snaps</h2>
  <figure class="fig"><img src="https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels/resolve/main/community.png" width="1920" height="1200" alt="Bar chart: distance gained toward the recto face over the published label, 71 fresh PHerc0814 and PHerc0841 sites pooled. labelsnap +2.15 voxels; one fixed offset for every vertex +0.77 (reference); seven community snaps from +0.26 to -0.41, and vc_objrefine with its shipped thresholds -9.72, off the scale." loading="lazy"></figure>
  <p>On 29 October 2026 the single-scan snap (labelsnap, the method used here for PHerc0172) ran once on fresh test sites of PHerc0814 and PHerc0841 next to seven community snaps, under a rule fixed before it ran. Truth is the recto face in a finer scan of the same scroll (1.129 µm for PHerc0814, 2.403 µm for PHerc0841), registered per site; 71 sites were scored. Pooled, labelsnap moved labels 2.15 voxels closer to that face than the published labels (95% interval 1.82 to 2.51) and 1.89 closer than VC3D's vc_objrefine with thresholds tuned on PHerc0139 (1.48 to 2.35). It was also closer than vc_objrefine as shipped, recto-offset r2 with and without its gate, surface_placement_audit, RectoRefine's midline and a snap onto a surface prediction, on each scroll and pooled. Within 1 voxel: 55% (PHerc0814) and 66% (PHerc0841) for labelsnap, 19% for the published labels on both, 22% and 21% for the best community snap. Every control held: reversing the move pushed labels away, a random sign gained nothing.</p>
  <p>Limits: PHerc0814 is held out by site, not by scroll. The test shows labels moved closer to the face, not every vertex within 1 voxel. A label displaced toward the verso was not shown to come back. The midline and nearest-peak snaps aim at the sheet center by design, so part of their loss is that target. Where a finer scan exists, finesnap did better than labelsnap on PHerc0814 by 0.93 voxels. The released PHerc0841 meshes were not scored here, because their finesnap read the same 2.403 µm scan this test used as truth.</p>
  <h2>What is in each segment folder</h2>
  <ul>
    <li><code>snapped.tifxyz/</code>: the moved mesh, same grid as the source; <code>-1</code> where there is no vertex or it was held back.</li>
    <li><code>abstain.tif</code>: 0 snapped (face measured at the vertex), 1 not measured and left at its published position, 2 not measured and moved by the offset filled in from measured neighbors (filled), 255 no vertex or held back. Version 1.0.1 added code 2; in 1.0.0 filled vertices were 1.</li>
    <li><code>confidence.tif</code> (0 to 1), <code>reason.tif</code> (why no face was measured), <code>source.tif</code> (finesnap: 1 fine scan, 2 label scan).</li>
    <li><code>release_mask.tif</code>: 0 released, 1 held back for evaluation, 255 not in the source mesh. <code>release.json</code>: source URLs, checksums and the summary.</li>
  </ul>
  <h2>Limits</h2>
  <p>A snap moves along the normal only; it does not fix a label that follows the wrong wrap. Where two sheets touch, the face it finds can belong to the neighbor. Small regions are held back for evaluation and five segments of PHerc0139 and one of PHerc0841 are not included. The meshes are geometry: they say nothing about ink or text.</p>
  <p class="credit">Scans and source meshes: Vesuvius Challenge open data, CC BY-NC 4.0; the snapped meshes are shared under the same terms. Page code Apache 2.0. Made by Chase Hendrick.</p>
</section>

<section data-pane="connect" hidden>
<!-- space-connect:start -->
<section class="scc" id="connect" aria-label="Connect your tool"><style>.scc{--a:var(--scc-accent,#4ea8de);color:inherit;font:inherit;line-height:1.5;max-width:60rem}
.scc h2{font-size:1.15em;margin:.2em 0 .3em}.scc h3{font-size:1em;margin:0 0 .2em}
.scc p{margin:.3em 0}.scc a{color:var(--a)}
.scc .scc-src{border:1px solid color-mix(in srgb,currentColor 18%,transparent);border-radius:10px;padding:.7em .9em;margin:.7em 0;background:color-mix(in srgb,currentColor 4%,transparent)}
.scc .scc-meta{font-size:.85em;opacity:.8}
.scc details{border-top:1px solid color-mix(in srgb,currentColor 12%,transparent);padding:.35em 0}
.scc summary{cursor:pointer;font-weight:600;list-style-position:inside}
.scc .scc-b{font-weight:400;font-size:.75em;padding:.05em .5em;border-radius:99px;margin-left:.5em;border:1px solid currentColor;opacity:.75;white-space:nowrap}
.scc .scc-b.ok{color:#3fb37f}.scc .scc-b.src{color:var(--a)}.scc .scc-b.warn{color:#e0a030}
.scc .scc-code{position:relative;margin:.4em 0 .2em}
.scc pre{margin:0;padding:.7em .8em;border-radius:8px;overflow:auto;font-size:.82em;background:color-mix(in srgb,currentColor 9%,transparent);white-space:pre}
.scc code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.scc button.scc-copy{all:unset;box-sizing:border-box;position:absolute;top:.35em;right:.35em;font-size:.75em;line-height:1.4;padding:.1em .6em;border-radius:6px;border:1px solid color-mix(in srgb,currentColor 30%,transparent);background:color-mix(in srgb,currentColor 8%,transparent);color:inherit;cursor:pointer}
.scc button.scc-copy:hover{border-color:var(--a)}
.scc .scc-url{position:relative}.scc .scc-url pre{padding-right:4.5em;white-space:pre-wrap;word-break:break-all}
.scc .scc-go{display:inline-block;margin:.3em 0;padding:.25em .8em;border-radius:6px;border:1px solid var(--a);text-decoration:none}
.scc footer{font-size:.8em;opacity:.75;margin-top:.6em}</style>
<h2>Connect your tool</h2>
<p>The snapped meshes, their records and the CT they sit on read straight from these URLs, logged out. Every segment is a tifxyz folder, so VC3D, villa and anything that reads tifxyz opens it as it is.</p>
<div class="scc-src" id="connect-data"><h3>Snapped labels: every segment, with index.json and checksums</h3>
<p class="scc-meta">CC BY-NC 4.0 (derived from Vesuvius Challenge open data) · One folder per segment, SCROLL/SEGMENT/: snapped.tifxyz, abstain.tif, confidence.tif, reason.tif, source.tif (finesnap), release_mask.tif and release.json (source URLs, sha256 of every file, summary). index.json lists every segment; viewer/ holds the page&#x27;s cross sections.</p>
<div class="scc-url"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels</code></pre></div>
<details><summary>Python (huggingface_hub)<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code># pip install huggingface_hub
from huggingface_hub import hf_hub_download, snapshot_download

path = hf_hub_download(&quot;SharpMeow/vesuvius-snapped-labels&quot;, &quot;index.json&quot;, repo_type=&quot;dataset&quot;)  # one file, cached
folder = snapshot_download(&quot;SharpMeow/vesuvius-snapped-labels&quot;, repo_type=&quot;dataset&quot;)</code></pre></div></details>
<details><summary>Command line (hf)<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>pip install -U huggingface_hub
hf download SharpMeow/vesuvius-snapped-labels index.json --repo-type dataset --local-dir vesuvius-snapped-labels</code></pre></div></details>
<details><summary>curl<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>curl -L -O https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels/resolve/main/index.json</code></pre></div></details>
</div>
<div class="scc-src" id="connect-mesh"><h3>One snapped mesh (tifxyz): PHerc0841 w00</h3>
<p class="scc-meta">CC BY-NC 4.0 (derived from Vesuvius Challenge open data) · Same grid and voxel frame as the published mesh it came from (release.json names it), so the two line up vertex for vertex; -1 where there is no vertex or it was held back.</p>
<div class="scc-url"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels/resolve/main/PHerc0841/20260220213127-w00/snapped.tifxyz</code></pre></div>
<details><summary>Python (numpy, tifffile)<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code># pip install numpy tifffile
import io, json, urllib.request
import numpy as np, tifffile

T = &quot;https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels/resolve/main/PHerc0841/20260220213127-w00/snapped.tifxyz&quot;
meta = json.load(urllib.request.urlopen(T + &quot;/meta.json&quot;))  # scale, bbox, format
get = lambda c: tifffile.imread(io.BytesIO(urllib.request.urlopen(f&quot;{T}/{c}.tif&quot;).read()))
xyz = np.stack([get(c) for c in &quot;xyz&quot;], -1)  # xyz[i, j] = (x, y, z) in scan voxels; -1 = no surface</code></pre></div></details>
</div>
<div class="scc-src" id="connect-ct"><h3>The CT that mesh is in, PHerc0841 9.366 um</h3>
<p class="scc-meta">CC BY-NC 4.0 (Vesuvius Challenge open data) · Read live from the open-data bucket, never copied here. Mesh coordinates are level-0 voxels of this scan. · <a href="https://scrollprize.org/data_browser/PHerc0841" target="_blank" rel="noopener">browse</a></p>
<div class="scc-url"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>https://vesuvius-challenge-open-data.s3.us-east-1.amazonaws.com/PHerc0841/volumes/20250821151531-9.366um-1.2m-113keV-masked.zarr</code></pre></div>
<details><summary>Python (zarr)<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code># pip install &quot;zarr&gt;=3&quot; fsspec aiohttp
import zarr

root = zarr.open_group(&quot;https://vesuvius-challenge-open-data.s3.us-east-1.amazonaws.com/PHerc0841/volumes/20250821151531-9.366um-1.2m-113keV-masked.zarr&quot;, mode=&quot;r&quot;)  # OME-Zarr, zarr v2
a = root[&quot;2&quot;]  # level 0 is full resolution; level L is 2**L times coarser
print(a.shape, a.dtype, a.chunks)
block = a[3600:3664, 600:664, 500:564]  # (z, y, x); reads only the chunks it touches</code></pre></div></details>
<details><summary>villa&#x27;s vesuvius package<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code># pip install &quot;vesuvius[volume-only]&quot;
from vesuvius import Volume

v = Volume(type=&quot;zarr&quot;, path=&quot;https://vesuvius-challenge-open-data.s3.us-east-1.amazonaws.com/PHerc0841/volumes/20250821151531-9.366um-1.2m-113keV-masked.zarr/2&quot;)  # one pyramid level
block = v[3600:3664, 600:664, 500:564]</code></pre></div></details>
<details><summary>VC3D<span class="scc-b src">from villa&#x27;s source</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>In VC3D (villa&#x27;s volume-cartographer), open or create a project, then
File &gt; Attach Remote Zarr... and paste:

https://vesuvius-challenge-open-data.s3.us-east-1.amazonaws.com/PHerc0841/volumes/20250821151531-9.366um-1.2m-113keV-masked.zarr

It accepts http, https and s3 OME-Zarr roots.</code></pre></div></details>
<details><summary>neuroglancer<span class="scc-b ok">tested 2026-10-24</span></summary>
<a class="scc-go" href="https://neuroglancer-demo.appspot.com/#!%7B%22layers%22%3A%5B%7B%22type%22%3A%22image%22%2C%22source%22%3A%22zarr%3A%2F%2Fhttps%3A%2F%2Fvesuvius-challenge-open-data.s3.us-east-1.amazonaws.com%2FPHerc0841%2Fvolumes%2F20250821151531-9.366um-1.2m-113keV-masked.zarr%2F%22%2C%22name%22%3A%22The%20CT%20that%20mesh%20is%20in%2C%20PHerc0841%209.366%20um%22%7D%5D%2C%22layout%22%3A%224panel%22%7D" target="_blank" rel="noopener">Open in neuroglancer</a>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>https://neuroglancer-demo.appspot.com/#!%7B%22layers%22%3A%5B%7B%22type%22%3A%22image%22%2C%22source%22%3A%22zarr%3A%2F%2Fhttps%3A%2F%2Fvesuvius-challenge-open-data.s3.us-east-1.amazonaws.com%2FPHerc0841%2Fvolumes%2F20250821151531-9.366um-1.2m-113keV-masked.zarr%2F%22%2C%22name%22%3A%22The%20CT%20that%20mesh%20is%20in%2C%20PHerc0841%209.366%20um%22%7D%5D%2C%22layout%22%3A%224panel%22%7D</code></pre></div></details>
<details><summary>curl<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>curl -s https://vesuvius-challenge-open-data.s3.us-east-1.amazonaws.com/PHerc0841/volumes/20250821151531-9.366um-1.2m-113keV-masked.zarr/.zattrs            # OME multiscales metadata
curl -s https://vesuvius-challenge-open-data.s3.us-east-1.amazonaws.com/PHerc0841/volumes/20250821151531-9.366um-1.2m-113keV-masked.zarr/2/.zarray     # one level: shape, chunks, dtype, codec</code></pre></div></details>
</div>
<div class="scc-src" id="connect-page"><h3>This page&#x27;s own files</h3>
<p class="scc-meta">Page code Apache 2.0; data as above · In the browser console, window.snappedLabels.segments() lists the index and window.snappedLabels.open(SEGMENT, Z) opens a segment at a plane; ?seg=SEGMENT&amp;z=Z links to a view.</p>
<div class="scc-url"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>https://sharpmeow-snapped-labels.static.hf.space/</code></pre></div>
<details><summary>Links and embed<span class="scc-b ok">tested 2026-10-24</span></summary>
<div class="scc-code"><button type="button" class="scc-copy" data-testid="connect-copy" onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentNode.querySelector('code').innerText).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1200)})">Copy</button><pre><code>The dataset card: https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels
A segment&#x27;s cross sections for the viewer (float32 rows, see the .json beside it): https://huggingface.co/datasets/SharpMeow/vesuvius-snapped-labels/resolve/main/viewer/PHerc0841/20260220213127-w00.json
Page source: https://github.com/ChaseHendrick/Scrolls/tree/main/spaces/snapped-labels</code></pre></div></details>
</div>
<footer>Machine-readable: <a href="https://huggingface.co/spaces/SharpMeow/snapped-labels/blob/main/connect.json" target="_blank" rel="noopener">connect.json</a> and <a href="https://huggingface.co/spaces/SharpMeow/snapped-labels/blob/main/CONNECT.md" target="_blank" rel="noopener">CONNECT.md</a>. Checked 2026-10-27. "Tested" means the snippet ran against this public data on that date. Scan data keeps its own license (the Vesuvius Challenge open data is CC BY-NC 4.0).</footer></section>
<!-- space-connect:end -->
</section>
</main>
<script src="app.js"></script>
<script src="vx.js"></script>
</body>
</html>