Perceptual color, closed form.
AxiomLab is a perceptual color space with a strictly positive-definite Riemannian metric, calibrated on 10,486 human color-difference pairs. No lookup tables, no iterative inverse — one closed-form pipeline from XYZ to a metric you can integrate.
- 18.18 Mean7 STRESS
- 0.03% ideal arc CV
- 2.33e-15 XYZ round-trip
- 1e-15 Python ↔ JS parity
Playground
Two colors, five metrics, one arc
Change either color to recompute AxiomLab, HelmLab and the standard metrics in your browser. Color A also seeds the page theme — generated in AxiomLab LCh, not HCT. Gradients are generated live along each space's own interpolation path.
AxiomLab coordinates of A
L 0.3956 · a -0.1335 · b -0.3844L
0.396
C
0.407
h°
250.9
Color difference
lower = more similar- AxiomLab — Power-Riemannian 0.8227
- AxiomLab — Homogeneous ds 0.7881
- HelmLab MetricSpace 0.1483
- CIEDE2000 64.2339
- OKLab (Euclidean) 0.6312
- CIE76 149.9606
The six columns use different units and scales. HelmLab's trained distance saturates near 0.15, so compare rankings within one metric — not raw magnitudes across metrics.
Gradient paths
Same endpoints, four interpolation strategies. Equal hex steps are shown; perceptual spacing differs.
AxiomLab
Riemannian arc-length
HelmLab
GenSpace + CIEDE2000 arc-length
OKLab
linear Lab interpolation
Linear sRGB
gamma-encoded interpolation
The blue→white test
Naive RGB and some Lab paths drift through lavender. AxiomLab bends the blue region toward a sky-blue midpoint (#88a7e6); HelmLab lands at #629eff.
Why it exists
One space, two jobs
Measurement and generation usually pull in opposite directions. AxiomLab keeps both: a trained power-Riemannian dE for near-threshold judgment, and a homogeneous degree-1 line element for arcs.
Two metrics, one tensor
The trained power form uses γd = 0.819 for near-threshold differences. The homogeneous form is degree-1, so doubling a step doubles the distance — the property arc-length integration needs.
γd
0.819
mean ideal arc CV
0.03%
tensor λmin
≥ 0.134
datasets
7
Grays stay gray
The achromatic axis is structural: the maximum chroma over the D65 gray ramp is 5.15e-14. The same transfer function generates the site theme, so neutral surfaces keep their tint without drifting in hue.
Invertible by construction
Quadratic Padé lightness plus an exact C¹ HDR extension. No search, no LUT, no branch drift.
sRGB round-trip
2.33e-15
HDR 100×
2.56e-13
Rec.2020
2.44e-15
JS ↔ Python
4.4e-16
Explore
See it in context
-
Playground
The two color pickers above drive every metric and every gradient — and the page theme itself.
-
Benchmarks
STRESS on 10,486 pairs, ablation, COMBVD cross-check, gradient uniformity and a live speed test.
-
API
Python and JavaScript quick start, the full function surface, the math, and how to reproduce every number.
Quick start
One dependency: NumPy
The Python package is pure NumPy; the JavaScript build is a single 18 KB file with no dependencies. Both implement the identical closed form.
Source installs work today. Registry uploads are pending; the plain pip install axiomlab and npm install axiomlab commands will return 404 until the first release is published.
import axiomlab as ax
lab = ax.from_hex("#3b82f6") # (L, a, b)
lch = ax.to_LCh(lab) # (L, C, h)
de = ax.difference("#ff0055", "#00aa88")
mid = ax.mix("#0000ff", "#ffffff", 0.5, metric_step=True)
ramp = ax.gradient("#0000ff", "#ffffff", 16, metric_step=True)