# Code, part two: dithering in time

Python 3 with numpy for everything; a C compiler only to regenerate the spatiotemporal blue-noise texture. Run
each from this folder. `filters.py`, `lattice.py`, `simulate.py` and `bluenoise.py` are copies of part one's, in the folder
above, and `pipeline.py` and `dithers.py` come from the starlock-glow entry, unchanged.

| file | what it does | how to run |
|---|---|---|
| `st.py` | Space-time lattices `((A x + B y + C t) mod N + 1/2) / N`: the exact error through a spatial filter and an eye model (a box over k frames, a decay, one frame), the shimmer in a band of temporal frequencies, the search over every (A, B, C). | imported |
| `brute.py` | Brute force, independent of the formulas: dither a periodic block of frames, round, filter each frame by direct shifts, blend over frames in the time domain. | imported |
| `check.py` | The formula against brute force: 54 cases (Starlock's full and lite passes, paint off; one frame, boxes, decays, the shimmer below 20 Hz). | `python3 check.py` (`out/check.txt`, about 4 minutes) |
| `vis.py` | How visible grain and shimmer are: each piece of the error weighted by the eye's sensitivity at its spatial and temporal frequency, pooled into JND. The generous `bright` model, its `dark` variant, Kelly's formula for comparison. | imported |
| `search.py` | Every (A, B, C) up to N levels through Starlock's pass and with paint off, under 8 eye models: the best, the best whose shimmer stays under the still grain, the least visible in all. | `python3 search.py` (`out/search.txt`, about a minute) |
| `floors.py` | The floors for any dither: a box over k frames (the still floor divided by k), a decay (Parseval in space and time), and a stronger numerical estimate for decays; against the best lattices. | `python3 floors.py` (`out/floors.txt`, a few minutes) |
| `temporal1d.py` | Paint off, one pixel: the best 0/1 sequence for a box (exact) and a decay (value iteration, then the policy run), against lattices, flipping and white noise. | `python3 temporal1d.py` (`out/temporal1d.txt`, a few minutes) |
| `golden.py` | The best still lattice moved by the golden ratio each frame: its formula (an irrational time step) against brute force. | `python3 golden.py` (`out/golden.txt`, under a minute) |
| `practical.py` | The dithers games use (IGN still, IGN with Wolfe's offset or the golden ratio or a half step every other frame, white noise, blue noise, spatiotemporal blue noise, lattices), by simulation: error per eye model, shimmer, grain and shimmer in JND. | imported |
| `compare.py` | The comparison table, through the pass and with paint off. | `python3 compare.py` (`out/compare.txt`, about 15 minutes) |
| `stbn.c`, `stbn64x32.npy` | Spatiotemporal blue noise by void-and-cluster with Wolfe et al.'s energy (frame or pixel shared); the 64×64×32 texture as 16-bit thresholds. | `cc -O2 -o stbn stbn.c -lm && ./stbn 64 32 1 > ranks.txt` (about a minute) |
| `pipe_t.py` | Starlock's real glow path frame after frame (both 8-bit writes, the pass, the tone curve), with the dither still, flipped by half a step every other frame, moved by the golden ratio or by Wolfe's offset; band and grain per eye model, grain and shimmer in JND at 60 and 30 fps. | `python3 pipe_t.py` (`out/pipe.txt`, about 20 minutes on 4 cores) |

Everything is deterministic except white noise (seeded) and the windowed spectra's small bias (they read a few
percent high or low against the exact formulas on lattices).
