API
Small surface, closed form
AxiomLab ships as a pure-NumPy Python package and a zero-dependency JavaScript file. Both expose the same conversions and the same two metrics; parity is tested to 1e-15.
Registry status: the npm and PyPI packages are not published yet. The source installs above work now; pip install axiomlab and npm install axiomlab will return 404 until the first release is uploaded.
Python
import axiomlab as ax
lab = ax.from_hex("#3b82f6") # AxiomLab (L, a, b)
lch = ax.to_LCh(lab) # (L, C, h)
xyz = ax.to_XYZ(lab) # back to CIE XYZ
d_power = ax.difference("#ff0055", "#00aa88")
d_homog = ax.difference("#ff0055", "#00aa88", use_power_law=False)
mid = ax.mix("#0000ff", "#ffffff", 0.5, metric_step=True)
ramp = ax.gradient("#0000ff", "#ffffff", 16, metric_step=True)JavaScript
const ax = require("axiomlab");
const lab = ax.fromHex("#3b82f6");
const lch = ax.toLCh(lab);
const dE = ax.difference("#ff0055", "#00aa88", { usePowerLaw: true });
const mid = ax.mix("#0000ff", "#ffffff", 0.5, true);
const ramp = ax.gradient("#0000ff", "#ffffff", 16, true);Function surface
| Function | Purpose |
|---|---|
| from_hex(hex) | sRGB hex → AxiomLab Lab |
| from_XYZ(xyz) | CIE XYZ (Y=1) → AxiomLab Lab |
| to_XYZ(lab) | AxiomLab Lab → CIE XYZ |
| to_LCh(lab) | Cartesian Lab → cylindrical LCh |
| difference(c1, c2, use_power_law=True) | Trained power-Riemannian ΔE |
| distance(xyz1, xyz2, use_power_law=False) | Homogeneous degree-1 Riemannian ds |
| euclidean_distance(xyz1, xyz2) | Plain Euclidean distance in AxiomLab |
| gamut_map(lab) | Project into sRGB by chroma reduction |
| mix(c1, c2, t, metric_step=True) | Arc-length color at fraction t |
| gradient(c1, c2, steps, metric_step=True) | Equal-arc gradient stops |
JavaScript names are camelCase: fromHex, difference, mix, gradient. Options are { usePowerLaw: false }, { forceScEqSh: true }, { disableRt: true }.
Pipeline
- 1. XYZ → LMS — fixed 3×3 matrix M₁.
- 2. Per-channel ψ — signed cbrt with an epsilon offset for finite slope at zero.
- 3. LMS′ → Lab₀ — fixed 3×3 matrix M₂.
- 4. Lightness — two-stage quadratic Padé on [0, 1.20], C¹ linear HDR extension above.
- 5. Chroma / hue — bounded three-shear warp, radial γ/β/G factors.
- 6. Helmholtz–Kohlrausch — bounded lightness shift from chroma.
The metric is a midpoint-evaluated positive-definite tensor in (L, a, b). The homogeneous line element ds = √(dxᵀ G(x̄) dx) is degree-1, so arc-length integration is
subdivision-invariant; the power form dE = ds^γd is the trained
near-threshold variant. AxiomLab reports both.
γd
0.819
mean arc CV
0.03%
tensor λmin
≥ 0.134
datasets
7
Reproduce every number
# unit + property tests
python3 test_axiomlab.py # 8 tests
node test_axiomlab.js
# dataset integrity
python3 build_datasets.py # 10,486 pairs, 7 datasets
# full verification: invertibility, STRESS, ablation, 5-fold CV,
# bootstrap CI, gradient uniformity, Python ↔ JS parity
python3 optimize_and_verify.py
# HelmLab comparison (downloads COMBVD on first run)
python3 benchmark_helmlab.pyLast run: Python tests 8/8, Node tests pass, 7 datasets verified, Python ↔ JS parity max 4.4e-16 (Lab) / 1.1e-15 (ΔE). HelmLab comparison: 3813 COMBVD pairs.
Credits and licenses
AxiomLab is MIT. The Svelte site's Material 3 token system, spring motion helpers, shape-morphing library and ripple attachment are adapted from material-expressive-svelte (MIT, Copyright © 2026 Oleg Polin); the shape library is itself derived from AOSP (Apache-2.0). HelmLab is MIT, Copyright © 2026 Görkem Yıldız. The HelmLab comparison uses its published package and dataset loader.
Repository