unroll / README.md
SharpMeow's picture
One page scroll bar and American English
757768f verified
|
Raw History Blame Contribute Delete
9.96 kB
---
title: Unroll
emoji: 📜
colorFrom: yellow
colorTo: gray
sdk: static
app_file: index.html
pinned: false
license: apache-2.0
short_description: Unroll a carbonized Herculaneum scroll in your browser
thumbnail: https://huggingface.co/spaces/SharpMeow/unroll/resolve/main/og.jpg
tags:
- vesuvius-challenge
- herculaneum
- three.js
- zerogpu
- computed-tomography
models:
- scrollprize/ink_9um
---
# Unroll
PHerc. 139 is a papyrus roll carbonized when Vesuvius buried Herculaneum in 79 CE. It cannot be opened, so it was scanned with X-rays at the ESRF synchrotron. This page rebuilds 37 of its windings in 3D from the public Vesuvius Challenge meshes and lets you unroll them in the browser. Ink layers show where models detect ink; letters visible here are candidates for expert reading.
- **Shapes**: the 9.362 µm tifxyz meshes of the 37 traced windings (`w023` to `w059`), decimated to 579,450 vertices.
- **X-ray layer**: the CT intensity on each surface, from the public 9.362 µm surface volumes.
- **Published ink (2.4 µm), amber**: the Vesuvius Challenge's public ink detection on the 2.4 µm scan. In 3D it is drawn through a local-contrast filter so letter-sized strokes stand out. The close-up view shows the published preview without filtering, downscaled to 2,400 px on its long side and re-saved as JPEG.
- **ink_9um (9 µm), cyan**: inked by running the public [`scrollprize/ink_9um`](https://huggingface.co/scrollprize/ink_9um) model (seed 42, step 75000) on the 9.4 µm scan (9.362 µm voxels). The ink_9um model was trained by the Vesuvius Challenge and run by Chase Hendrick, on Hugging Face ZeroGPU and Modal, over all 37 windings (`w023` to `w059`). The first batch was 37,141 patches in 57 s of measured GPU time. The page reads the covered windings from the manifest, so its text updates as windings are added. The 9.4 µm scan (9.362 µm voxels) is about four times coarser than the 2.4 µm one, so this layer is noisier. `w047` and `w050` ran with patch overlap 0.5; others ran with 0.25 or 0.2, and their 128 px patch grid shows as faint square tiles. Per-run records (checkpoint sha256, villa commit, requested and measured GPU seconds) are in `data/gpu/receipts/`; `data/gpu.json` is the summary the page reads.
Unrolling lays the windings end to end, outermost first. Each traced winding runs a little past one full turn, so roughly a tenth of the 2.8 m strip repeats surface from its neighbor.
## Release
Unroll is a released tool: an interactive 3D viewer that virtually unrolls Herculaneum scroll scans with ink layers, an Ink Bench for comparing ink models, and an agent API.
- Status: released, v1.0.0.
- Version: 1.7.1 (`version.json`, [CHANGELOG.md](CHANGELOG.md)). The page shows it in the About panel and `window.unroll.version()` returns it.
- License: Apache 2.0 for all code (`LICENSE`, `NOTICE`). The scan data in `data/` and `og.jpg` are CC BY-NC 4.0. three.js keeps its own license (see `NOTICE`).
- Install app: open [the app page](https://sharpmeow-unroll.static.hf.space/) and press **Install app** (View panel or Settings), or use the browser's install icon. It works offline after the first visit; see [Install app](#install-app).
- Listed in the public repository: [ChaseHendrick/Scrolls](https://github.com/ChaseHendrick/Scrolls#released-tools).
## Install app
Unroll is a progressive web app. Install it and it opens in its own window and works with no network connection.
1. Open [sharpmeow-unroll.static.hf.space](https://sharpmeow-unroll.static.hf.space/) (the Space page embeds the app in a frame, where browsers do not offer installation; the **Install app** button there opens this page for you).
2. Press **Install app** in the View panel or in Settings. In Chrome and Edge you can also use the install icon in the address bar. In Safari on iPhone and iPad: Share, then Add to Home Screen. In Safari on macOS: File, then Add to Dock.
3. The page, three.js and the default scroll are kept on your device. Other scrolls and close-ups are kept after you view them once.
Agents can call `window.unrollView.action('install')` and read `window.unrollView.pwa.state()`. The service worker (`sw.js`) is registered as `sw.js?v=<version>-<sha>` from `version.json`, so each stamped build uses fresh caches (`unroll-shell-<tag>`, `unroll-data-<tag>`, `unroll-runtime-<tag>`) and deletes the old ones.
## Scrolls, windings and layers
The page is data driven. `scrolls/index.json` lists the scrolls and each one has a manifest (`scrolls/PHerc0139/manifest.json`) naming its windings, meshes, ink layers, sources, resolutions, credits and data terms. With more than one scroll a picker appears. `node tools/validate_scroll.mjs` checks the registry and every manifest with the same validator the page uses. See [docs/ADDING_A_SCROLL.md](docs/ADDING_A_SCROLL.md) to add one; `tools/precompute_template.py` is a starting point for building a package.
The atlases ship as WebP (`data/atlas_*.webp`), with the JPGs kept as a fallback.
## Open your own
Press **+** to unroll your own scroll: a zip, a folder, or a manifest with OBJ or PLY meshes (with UVs) and PNG, JPG or TIFF layers, or the URL of one (the server must allow CORS). Everything is read in your browser and kept in its storage; nothing is uploaded. The sheet has a downloadable synthetic example package. Details and limits are in [docs/ADDING_A_SCROLL.md](docs/ADDING_A_SCROLL.md#open-your-own).
## Live sheet
[`live.html`](live.html) streams any public traced segment (tifxyz) and a scan volume (CT, or a 3D ink prediction) from the open data bucket and shows the volume on the sheet in 3D, sampled in your browser along the sheet's normal. It can save the mesh as VTK for Neuroglancer or ParaView. Details: [docs/LIVE.md](docs/LIVE.md).
## Destroy mode
Just for fun, not a real unrolling. Press **Destroy** (T) to tear (X), crush (C), burn (B) or soak (W) the scroll at any unroll amount; the damage follows the sheet as it rolls and unrolls. Smoke, ash and burnt flakes rise from each ember where it is on the sheet right now. Debris lands on a soft floor that sits just below the scroll as currently drawn, rolled or unrolled, and fades soon after landing.
**Crumble** (K, or `unrollView.crumble()` in the console) breaks the whole scroll up from its edges inward over about four seconds; the pieces are pulled in toward the middle and fall into a heap of dust on the floor. **Reset** restores the scroll and clears all damage, debris and the heap. Particle and fragment counts stay capped (about 1,800 particles, 600 fragments and 2,600 heap grains on desktop, less on phones).
Why the tools behave as they do, with sources: [docs/REALISM.md](docs/REALISM.md).
For testing, `unrollView.damageStats()` reports the counts, the floor height, `stillAirMax` (longest any debris hung still above the floor, should stay 0) and `stillMax`.
## Rebuilding the data
From the Space's root, with Python 3, `numpy`, `scipy`, `tifffile`, `Pillow` and `curl`:
1. `python tools/fetch.py` lists the public bucket and downloads the meshes and ink previews into `raw/` (about 110 MB).
2. `python tools/build.py` writes `data/scroll.bin`, `data/scroll.json`, the atlases and `data/hi/`. It reads the X-ray layer straight from the bucket. `UNROLL_STEP` (default 3) sets the mesh coarseness; `python tools/build.py --coarsen 2 data/<scroll>` writes a lighter `scroll_lite.*` copy for phones without new downloads.
3. `python tools/gpu_layer.py` rebuilds the ink_9um (9 µm) layer. It needs the ink_9um output TIFFs in `gpu/wNNN/` (about 25 MB each, not shipped). Regenerate them with the model card's inference command on the surface-volume URLs in `data/gpu/receipts/`.
## License and credits
Data: Giorgio Angelotti, Stephen Parsons, Sean Johnson, Elian Rafael Dal Prà, Johannes Rudolph, Paul Tafforeau, Alessandro Mirone, Paul Henderson, Hendrik Schilling, Forrest McDonald, David Josey, Youssef Nader, C. Seth Parker, W. Brent Seales. *Vesuvius Challenge - CT Scans of Herculaneum Papyri.* Vesuvius Challenge. [Data browser for PHerc. 139](https://scrollprize.org/data_browser/PHerc0139). PHerc. 139 is held by the Biblioteca Nazionale di Napoli.
`data/` and `og.jpg` are derived from that data and are licensed [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/). The code (`index.html`, `style.css`, `app.js`, `tear.js`, `polish.js`, `lib/`, `scrolls/*.json` and `tools/`) is Apache 2.0, see `LICENSE` and `NOTICE`. The page uses [three.js](https://threejs.org) 0.160 from jsDelivr, which keeps its own MIT license.
## Ink Bench
Score your own ink prediction for any winding against the published ink, in the browser (nothing is uploaded): automatic UV alignment, side by side, swipe and difference views, Pearson r, IoU, Dice and a precision and recall curve (agreement with another model's output, not ground truth), letter boxes marked "candidate for expert review", and a one-click reproducible bundle. `tools/inkbench.py` gives identical results in Python and on the command line. See [docs/BENCH.md](docs/BENCH.md) and the open bundle format [docs/BENCH_FORMAT.md](docs/BENCH_FORMAT.md). The Bench code and format are Apache-2.0 (`LICENSE`, `NOTICE`, by Chase Hendrick), like the rest of the code; the data stays CC BY-NC 4.0.
### Researcher takeaway
On the public ink_9um run over all 37 windings (`docs/examples/bench/`), against the published 2.4 µm ink: median AP 0.319 for ink_9um, 0.117 for raw X-ray intensity and 0.089 for uniform noise, and ink_9um beats X-ray intensity on AP on every winding. On Pearson r the medians are 0.422, 0.266 and 0.000, but X-ray intensity outranks ink_9um on `w039`, `w053`, `w054` and `w057`. So: rank ink models by AP (threshold-free and robust to brightness), always report the X-ray floor next to your model, and look at windings where the floor wins before trusting a correlation. These are agreement scores with another model's output, not ground truth.