# Hecate ink detection on a laptop's integrated graphics `hecate_directml.py` makes GPU-accelerated Hecate 9.6 µm ink detection usable on a 16 GB Windows laptop with integrated graphics and shared system memory. The tested prediction path requires no discrete graphics card or rented GPU compute. This lowers the hardware barrier for contributors who already own a laptop but lack a dedicated GPU. They can run the released detector and test rendered regions locally, with faster feedback than the CPU path. The implementation uses ONNX Runtime DirectML to reach the laptop's existing graphics hardware; it preserves the released model and probability-image format. The demonstrated machine has a Ryzen 5 8540U with **Radeon 740M integrated graphics**, Windows 11 and **16 GB RAM**. A real PHerc0139 crop took **3.54 s**, compared with **13.02 s** for the original CPU predictor: **3.68× faster**, with all 9,216 output pixels identical. These timings cover tiled prediction and blending after model/session loading. They exclude export and initialization. ## Install and run Use Windows and a DirectX 12 GPU. The tested machine has Windows 11, a Ryzen 5 8540U, Radeon 740M integrated graphics, and 16 GB RAM. Other DirectML devices have not been tested here. Keep the helper beside the released `hecate.py`, `requirements.txt`, and `hecate_9.6um.pth`. These commands reproduce the tested Python 3.11 / CPU PyTorch environment. Use a separate environment from installations containing `onnxruntime` or `onnxruntime-gpu`: ```powershell python -m venv .venv .venv\Scripts\python -m pip install torch==2.10.0 --index-url https://download.pytorch.org/whl/cpu .venv\Scripts\python -m pip install -r requirements.txt -r requirements-directml.txt .venv\Scripts\python hecate_directml.py export --checkpoint hecate_9.6um.pth --output hecate_9.6um.onnx .venv\Scripts\python hecate_directml.py predict --model hecate_9.6um.onnx --input surface.zarr --spacing-um 9.6 --output ink.png ``` Export creates a roughly 513 MB ONNX file and a small `.onnx.json` sidecar. Keep both. The sidecar binds the graph to its checkpoint hash. Export once and reuse it; the measured export took 9.94 s. Allow about 5 GB of free system commit capacity for the verification process. Run export separately from other model jobs. Inputs must be unnormalized uint8 surface renders in Z,Y,X order, already sampled near 9.6 µm in all axes. A local Zarr array, a Zarr group containing `0`, or `.npy` is accepted. `--array` selects another array within a group. The spacing argument checks the declared spacing; it does not resample a raw scan. `--reverse` reverses the full depth before selecting the central 16 planes. `--stride` defaults to 32; `--device-id` selects the DirectML adapter, with 0 as the default. `--profile` records executed providers. CPU fallback is disabled; an unsupported graph fails instead of silently running on CPU. The output is a grayscale PNG with `round(255 * probability)`, plus JSON settings and timings. There is no per-image contrast scaling. The source Hann overlap, empty-column mask and padded-edge behavior are preserved. Accumulators use temporary disk files, approximately eight bytes per output pixel, plus one byte per pixel for the output buffer. Set `TMP` to a drive with adequate space for large surfaces. This helper supports **9.6 µm, FP32, batch size one, 2D output**. It does not implement training, the 2.4 µm checkpoint or 3D export. DirectML acceleration changes execution, not the detector's accuracy. ## Reproduce the comparison The source was pinned to Hecate revision `9cb86e500e944b11a06a7020403cde5dffb5bcb2`. The checkpoint SHA-256 is `809f4f10f7cb7afa19b4bee0f7d2ab31edd7e11b664f9f210cc9c17f22fcfe5d`. The example comes from PHerc0139, segment `20260112000000-w043_2026011217`, native scan `20250728140407`, 9.362 µm surface volume. `fetch_example.py` downloads four hash-checked chunks from the official server and reconstructs the exact comparison crop. CT data and model weights are not bundled with this contribution. The [data terms](https://dl.ash2txt.org/LICENSE.txt) apply to the downloaded data. ```powershell .venv\Scripts\python -m pip install -r requirements-verify.txt .venv\Scripts\python fetch_example.py --output pherc0139_crop.npy .venv\Scripts\python verify_directml.py --checkpoint hecate_9.6um.pth --input pherc0139_crop.npy --output check ``` The crop is 16×96×96. Its depth spacing is 9.6 µm; its effective XY spacing is 9.6059 µm after rounding the original 512-pixel extent to 499 pixels. Exact depth coordinates, interpolation and source hashes are in `fetch_example.py`. The reconstructed `.npy` SHA-256 is `04224e26f565c4a5c1ff7f018e4904a381e7d0d6a217a6ade09ab6ec313e312a`. The check runs the original CPU predictor, exports the model, and runs DirectML in separate processes. It requires each comparison to differ by at most one uint8 level, an exact repeated GPU image, exact equality between the array API and Zarr-to-PNG command, and cleanup after injected inference/writer errors. The observed differences were zero in every case: | Input | CPU prediction | DirectML prediction | Maximum pixel difference | |---|---:|---:|---:| | Real crop, four overlapping tiles | 13.018 s | 3.538 s | 0 | | Reversed depth | 12.973 s | 3.477 s | 0 | | Real crop cut to 45×53, with padding | 3.299 s | 0.923 s | 0 | | Real crop with nine empty columns | 13.231 s | 3.571 s | 0 | | Blank negative control | 0.004 s | 0.009 s | 0 | The fresh Zarr-to-PNG command took 5.313 s including session initialization. The graph profile contains only DirectML dispatches. The CPU reference used four threads; both paths ran in FP32 on the same laptop. Raw measurements and source/code hashes are in `directml_validation.json`. ![CPU and integrated-GPU pixel comparison](https://huggingface.co/scrollprize/hecate/resolve/468a7bceb71f00edc4a2aca41fcd7ef89d79a870/directml_comparison.png) The altered and blank inputs are boundary controls, not additional independent scroll examples. This is an exposed backend-equivalence comparison, not held-out accuracy validation or a claim of newly recovered letters. ## Implementation and attribution The helper reuses `hecate.py` for Zarr opening, tile origins and PNG writing. It uses the same intensity division and floored Hann blend. At 9.6 µm, the attention and output use the same XY grid. The validity mask is constant through depth for each column, so masking empty columns after inference gives the source result. This argument does not extend to the 2.4 µm spatial interpolation path. Hecate and its released weights are by the Vesuvius Challenge team. This optional backend was developed and tested with Codex during Mohamad Al-Zawahreh's scroll-recovery work. It does not retrain or replace the model. Tested software: Python 3.11.9, PyTorch 2.10.0+cpu, ONNX 1.23.2 and ONNX Runtime DirectML 1.24.4.