A data-driven analytical color space trained on 64,000 human color-difference observations
Project description
Helmlab
A data-driven analytical color space for UI design systems.
Helmlab is a family of purpose-built color spaces: MetricSpace (72-parameter enriched pipeline for perceptual distance) and GenSpace (generation-optimized pipeline for gradients and palettes). MetricSpace achieves STRESS 23.30 on COMBVD (3,813 color pairs) — a 20.1% improvement over CIEDE2000. GenSpace + arc-length reparameterization produces perfectly uniform gradients (CV ≈ 0% on any color pair).
Interactive Demo | Tools | Documentation | Paper
Key Features
- State-of-the-art color difference prediction — STRESS 23.30 vs CIEDE2000's 29.18 (MetricSpace)
- Perfectly uniform gradients — CIEDE2000 arc-length reparameterization, CV ≈ 0% on any pair (GenSpace)
- Achromatic guarantee — Grays map to C < 10⁻⁶ via neutral correction (no color artifacts in gradients)
- Free hue improvement — Rigid rotation reduces hue error (RMS 16.1°) at zero cost to the distance metric
- Embedded Helmholtz-Kohlrausch — Lightness is chroma-dependent, learned from data
- UI tooling — Gamut mapping, WCAG contrast enforcement, palette generation, dark/light mode adaptation
- Token export — CSS (
oklch()), Android XML, iOS Swift (Display P3), Tailwind, JSON
Installation
npm (TypeScript / JavaScript)
npm install helmlab
import { Helmlab } from 'helmlab';
const hl = new Helmlab();
const lab = hl.fromHex('#3B82F6'); // Hex → Helmlab Lab
const hex = hl.toHex([0.5, -0.1, 0.2]); // Lab → hex (gamut mapped)
hl.contrastRatio('#ffffff', '#3B82F6'); // → 3.68
hl.ensureContrast('#3B82F6', '#ffffff', 4.5); // Adjust to meet 4.5:1
hl.deltaE('#ff0000', '#00ff00'); // Perceptual distance
hl.gradient('#ff0000', '#0000ff', 8); // Perfectly uniform gradient
hl.semanticScale('#3B82F6'); // Tailwind-style 50–950 scale
~12KB gzipped, zero dependencies, ESM + CJS with full TypeScript types. See the npm package README for the full API.
Python (pip)
pip install helmlab
Quick Start (Python)
from helmlab import Helmlab
hl = Helmlab()
# sRGB to Helmlab Lab
lab = hl.from_srgb([0.2, 0.5, 0.8])
print(f"L={lab[0]:.3f}, a={lab[1]:.3f}, b={lab[2]:.3f}")
# Color difference between two sRGB colors
dist = hl.delta_e("#ff0000", "#00ff00")
# Perfectly uniform gradient (arc-length reparameterized)
gradient = hl.gradient("#ff0000", "#0000ff", 8)
# Ensure WCAG AA contrast (4.5:1)
adjusted = hl.ensure_contrast("#ffffff", "#3B82F6", min_ratio=4.5)
# Generate a palette (Tailwind-style 50-950 scale)
scale = hl.semantic_scale("#3B82F6")
Architecture
Helmlab is a family of purpose-built color spaces:
Helmlab (UI layer)
├── MetricSpace — 72-param enriched pipeline (distance, deltaE)
│ XYZ → M₁ → γ → M₂ → Hue → H-K → L → C → HL → NC → φ → Lab
│
└── GenSpace — generation-optimized pipeline (gradient, palette)
XYZ → M₁ → γ=⅓ → M₂ → NC → Lab
+ CIEDE2000 arc-length reparameterization for gradient()
MetricSpace (72 parameters) is jointly optimized against COMBVD using L-BFGS-B with 8 random restarts. 13-stage enriched pipeline with hue correction, Helmholtz-Kohlrausch, chroma scaling, neutral correction, and rigid rotation.
GenSpace (21 parameters) uses Phase1H-optimized M1/M2 matrices with shared γ=⅓. No enrichment stages — pure linear-algebra pipeline, fast and invertible. 6× better hue accuracy than Oklab (5.2° vs 30.1° RMS).
Benchmarks
Perceptual Distance (MetricSpace)
STRESS on COMBVD (3,813 pairs). Each method uses its standard distance formula. Lower is better.
| Method | COMBVD STRESS | vs CIEDE2000 |
|---|---|---|
| Helmlab v20b | 23.30 | -20.1% |
| CIEDE2000 | 29.18 | — |
| CIE94 | 33.59 | +15.1% |
| CAM16-UCS (Euclid.) | 33.90 | +16.2% |
| ΔE CMC | 34.04 | +16.6% |
| IPT (Euclid.) | 41.21 | +41.3% |
| CIE Lab ΔE76 | 42.80 | +46.7% |
| Oklab (Euclid.) | 47.46 | +62.7% |
Bootstrap (10,000 iterations): Helmlab 95% CI [22.50, 23.93], CIEDE2000 95% CI [27.64, 30.84]. Zero overlap, p < 10⁻⁴.
Gradient Uniformity (GenSpace + arc-length)
CV (coefficient of variation of CIEDE2000 step sizes). Lower is better.
| Method | Red→Blue | Orange→Cyan | Black→White |
|---|---|---|---|
| Helmlab | ≈ 0% | ≈ 0% | ≈ 0% |
| Oklab | 31.5% | 41.4% | 41.2% |
| CIE Lab | 44.8% | 52.3% | 61.5% |
Project Structure
src/helmlab/
├── helmlab.py # Main API (Helmlab class)
├── spaces/
│ ├── metric.py # MetricSpace — 72-param enriched pipeline
│ ├── gen.py # GenSpace — generation-optimized pipeline
│ ├── analytical.py # Compatibility shim → MetricSpace
│ ├── base.py # Abstract base class
│ ├── registry.py # Color space registry
│ └── ... # Baseline spaces (CAM16, IPT, Oklch, etc.)
├── metrics/
│ ├── delta_e.py # Color difference formulas
│ ├── stress.py # STRESS computation
│ └── benchmarks.py # Cross-method benchmarking
├── utils/
│ ├── srgb_convert.py # sRGB/Display P3 conversions
│ ├── gamut.py # Gamut mapping (binary search)
│ └── ... # Converters, I/O, visualization
├── data/
│ ├── metric_params.json # MetricSpace params (v20b, STRESS 23.30)
│ ├── gen_params.json # GenSpace params (Phase1H optimized)
│ └── ... # Dataset loaders (COMBVD, Munsell, etc.)
├── export.py # Token export (CSS, Android, iOS, Tailwind)
└── feedback/ # Human feedback collection tools
packages/helmlab-js/ # npm package (TypeScript)
docs/ # Documentation + interactive demo
paper/ # LaTeX paper + figures
tests/ # 337 tests (233 Python + 104 JavaScript)
Tests
python -m pytest tests/ -q # 233 Python tests
cd packages/helmlab-js && npx vitest run # 104 JS tests
Citation
@article{yildiz2025helmlab,
title={Helmlab: A Data-Driven Analytical Color Space for UI Design Systems},
author={Y{\i}ld{\i}z, G{\"o}rkem},
journal={arXiv preprint arXiv:2602.23010},
year={2025},
url={https://arxiv.org/abs/2602.23010}
}
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file helmlab-0.6.0.tar.gz.
File metadata
- Download URL: helmlab-0.6.0.tar.gz
- Upload date:
- Size: 92.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a829d87fd72056405cd6e600cb5ab1e0a02d83d2e47638779b1d697e2e2f0f29
|
|
| MD5 |
9bce3b6cc1d4429566cc716cacc18b3e
|
|
| BLAKE2b-256 |
647d0677015aa7d18671741f77f20b5e37573c641ee1e6b835e9fba05490f37c
|
File details
Details for the file helmlab-0.6.0-py3-none-any.whl.
File metadata
- Download URL: helmlab-0.6.0-py3-none-any.whl
- Upload date:
- Size: 84.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdee66b9ef802af9ea3d6bb7621beaf5fdb218b1a5f3758b4413f0234bafc66c
|
|
| MD5 |
e00d73faa797da46c07975f3e11b89db
|
|
| BLAKE2b-256 |
38fadf41368b906aa0d48d37df4d48a3f0c9d3365d7fc279e9f10c5a7747f2c5
|