Skip to main content

Helmlab

A family of purpose-built color spaces for UI design systems.

Helmlab provides two complementary color spaces: MetricSpace for perceptual distance measurement (STRESS 22.48 on COMBVD with Bradford CAT — 23% better than CIEDE2000's 29.20), and GenSpace for gradient/palette generation (62-9-19 vs OKLab on ColorBench's 90 metrics including independent datasets, 360/360/360 gamut cusps, zero monotonicity violations in sRGB/P3 — 1 in Rec.2020).

arXiv npm version PyPI version Color.js

Website | Documentation | Playground | Paper

Key Features

  • State-of-the-art color difference — MetricSpace: STRESS 22.48 vs CIEDE2000's 29.20 on COMBVD (3,813 pairs, with Bradford CAT pre-processing)
  • Superior gradient generation — GenSpace: 62 wins vs OKLab's 9 (19 ties) across 90 ColorBench metrics (3,038 gradient pairs, 3 gamuts), 360/360/360 valid cusps, zero monotonicity violations in sRGB/P3 (1 in Rec.2020)
  • Depressed cubic transfery³ + αy = x (α=0.021): eliminates cusp singularities while preserving gradient quality. Exact analytical inverse via hyperbolic functions
  • Chroma power — Mild compression (C^0.978) improves gradient step uniformity across 3,038 pairs
  • L-gated hue enrichment — Targeted hue rotation in the blue region, gated by lightness. Fixes blue→white purple shift without affecting other colors
  • True blue gradients — Blue→White midpoint is sky blue (G/R = 1.51), not lavender
  • Perfect achromatic axis — Grays map to C* ≈ 10⁻¹⁵ (structural guarantee from uniform transfer function)
  • Perfectly uniform gradients — Built-in CIEDE2000 arc-length reparameterization, CV ≈ 0% on any pair
  • Embedded Helmholtz-Kohlrausch — MetricSpace: 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 version bundle size

npm install helmlab
import { Helmlab } from 'helmlab';

const hl = new Helmlab();

hl.gen.gradient('#ff0000', '#0000ff', 8);             // Perfectly uniform gradient
hl.gen.gradient('#00f', '#fff', 8, { gamut: 'display-p3' }); // wide-gamut output
hl.gen.scale('#3B82F6');                              // Tailwind-style 50-950 scale
hl.gen.harmonies('#3B82F6', 'triadic');               // constant-L,C hue rotations
hl.gen.vivid('#6488b8', { gamut: 'display-p3' });     // chroma to the gamut boundary
hl.gen.ensureContrast('#3B82F6', '#ffffff', 4.5);     // adjust to meet 4.5:1
hl.metric.difference('#ff0000', '#00ff00');           // trained perceptual metric
hl.metric.jnd('#808080', '#828282');                  // just-noticeable-difference units
hl.metric.ciede2000('#ff0000', '#00ff00');            // industry standard, ~86.6
hl.tokens.css('#3B82F6', 'oklch');                    // design-token export

~17.8KB gzipped, zero dependencies, ESM + CJS with full TypeScript types. Full API reference: helmlab.space/docs.

PostCSS

npm version

Use Helmlab color spaces directly in CSS — transformed to rgb() at build time:

npm install postcss-helmlab
/* Input */
.card { color: helmlab(0.78 0.52 -0.20); }
.bg   { background: linear-gradient(in helmgen, #e63946, #457b9d); }

/* Output */
.card { color: rgb(255, 76, 119); }
.bg   { background: linear-gradient(#e63946 0.0%, ..., #457b9d 100.0%); }

Python (pip)

PyPI version

pip install helmlab

Quick Start (Python)

One Helmlab instance, three namespaces: hl.gen creates colors, hl.metric measures them, hl.tokens exports design tokens. The two spaces have branded Lab types — mixing them raises a TypeError instead of silently producing a wrong color.

from helmlab import Helmlab

hl = Helmlab()

# ── Create (GenSpace) ──────────────────────────────────────────────
hl.gen.gradient("#ff0000", "#0000ff", 8)              # equal perceptual steps
hl.gen.gradient("#0000ff", "#ffffff", 8, gamut="display-p3")  # wide-gamut output
hl.gen.mix("#ff0000", "#0000ff")                      # visual midpoint (same path)
hl.gen.scale("#3b82f6")                               # Tailwind 50-950, 500 == input
hl.gen.harmonies("#3b82f6", "triadic")                # constant-L,C hue rotations
hl.gen.vivid("#6488b8", gamut="display-p3")           # chroma -> gamut boundary
hl.gen.cusp(263)                                      # most colorful point of a hue
hl.gen.ensure_contrast("#ffffff", "#3b82f6", ratio=4.5, strict=True)

# ── Measure (MetricSpace) ──────────────────────────────────────────
hl.metric.difference("#ff0000", "#00ff00")   # trained metric (COMBVD 22.48)
hl.metric.jnd("#808080", "#828282")          # in just-noticeable-difference units
hl.metric.ciede2000("#ff0000", "#00ff00")    # industry standard, ~86.6
hl.metric.confidence("#808080", "#828282")   # observer-disagreement estimate
hl.metric.info("color(display-p3 1 0 0)")    # wide-gamut input works everywhere

# ── Export (hex in, tokens out) ────────────────────────────────────
hl.tokens.css("#3b82f6", "oklch")            # 'oklch(62.3% 0.1881 259.8)'
hl.tokens.css_variables(hl.gen.scale("#3b82f6"), "--primary")

JS is the camelCase mirror (hl.gen.ensureContrast(...)). Parity is enforced by a permanent cross-language gate: every string output is byte-identical, numeric worst-case difference ~1e-12, and hex round-trips are bit-exact on a 1728-color grid in both spaces and both languages. Full surface: API.md. Upgrading from 0.x: the flat hl.gradient()/hl.from_hex() API was removed in 1.0 — every method now lives on hl.gen / hl.metric / hl.tokens.

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₁ → depcubic(α) → M₂ → PW_L_corr → L-gated enrichment → C^cp → NC → Lab
    + CIEDE2000 arc-length reparameterization for gradient()

MetricSpace (72 parameters)

Jointly optimized with CMA-ES against COMBVD (with Bradford CAT pre-processing). 13-stage enriched pipeline with hue correction, Helmholtz-Kohlrausch, chroma scaling, neutral correction, and rigid rotation. STRESS 22.48 with Bradford CAT (22.73 without) — the lowest published figure on COMBVD; cross-validated estimate ~24.3.

GenSpace (v0.11.1 — Depressed Cubic + Chroma Power + L-Gated Enrichment)

Pipeline: XYZ → M₁ → depcubic(α=0.021) → M₂ → PW L_corr → L-gated hue enrichment → chroma_power(0.978) → NC → Lab

Transfer function: y³ + αy = x (depressed cubic, α=0.021)

Solved analytically via y = 2s·sinh(arcsinh(x/2s³)/3) where s = √(α/3), refined with a single Halley iteration for full precision. The inverse is trivial: x = y³ + αy. This depressed cubic has a finite derivative at zero (unlike standard x^(1/3)), which eliminates gamut boundary singularities.

Chroma power: C' = C^0.978 — mild chroma compression applied post-M2 that improves gradient step uniformity. Analytically invertible (C = C'^(1/0.978)).

L-gated hue enrichment: A targeted hue rotation h' = h + A·gate(L)·gauss(h−center) applied post-M2, where the gate function sin²(π·(L−L_lo)/(L_hi−L_lo)) activates only in mid-to-high lightness and the Gaussian targets the blue hue region. This fixes the blue→white purple shift with zero impact on achromatic colors or other hue regions. Invertible via Halley iteration (cubic convergence, 8 iterations).

Key properties:

  • 360/360/360 valid cusps in sRGB, Display P3, and Rec.2020 (OKLab: 299/308/360)
  • Zero invalid cusps across all gamuts; zero monotonicity violations in sRGB/P3 (1 in Rec.2020)
  • Blue→White gradient: sky blue midpoint (G/R = 1.51), no lavender shift
  • Achromatic: C* ≈ 10⁻¹⁵ (structural guarantee — uniform transfer × orthogonal M₂)
  • Munsell Value uniformity: 0.16% (OKLab: 2.80% — 18x better)
  • Adaptive gamut clipping with cusp-finding (Ottosson-style L0 calculation)
  • Piecewise-linear L correction with 19 breakpoints (analytically invertible)

ColorBench evaluation (90 metrics, 3,038 gradient pairs, 3 gamuts):

Category GenSpace wins OKLab wins Tie
Gamut geometry 24 0 3
Application 8 1 3
Independent (Hung-Berns, Ebner-Fairchild, Pointer) 6 1 0
Gradient quality 5 3 3
Perceptual accuracy 5 0 0
Structural 4 2 2
Achromatic 2 0 0
Advanced 2 0 4
Hue 2 0 0
Special 2 1 0
Accessibility 1 1 0
Banding 1 0 1
Numerical stability 0 0 3
Total 62 9 19

Known trade-offs: Slightly reduced round-trip precision in sRGB (~5.6×10⁻⁸ vs OKLab's ~1.6×10⁻¹⁵, due to enrichment Halley iteration — invisible in 8-bit pipelines), minor primary hue discontinuity at exact primary vertices, and reduced near-achromatic gradient uniformity in very low chroma regions.

Blue-region gamut fold: All power-law based M1→f→M2 spaces exhibit tiny non-contiguous gamut regions near h≈260° in sRGB due to cubic polynomial roots in the inverse. OKLab has 46 such holes; GenSpace has 5, each ~0.001 chroma wide (sub-pixel, invisible). See color.js#81.

Benchmarks

Perceptual Distance (MetricSpace)

STRESS on COMBVD (3,813 pairs), all methods without CAT for a like-for-like protocol. Lower is better. (With Bradford CAT pre-processing Helmlab v21 reaches the headline 22.48.)

Method COMBVD STRESS vs CIEDE2000
Helmlab v21 22.73 -22.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%
How was STRESS measured?

STRESS (Standardized Residual Sum of Squares) is the CIE-standard metric for evaluating color difference formulas. COMBVD is a combined visual-difference dataset of 3,813 color pairs from 6 independent psychophysical experiments (Luo & Rigg 1986, RIT-DuPont, Witt, Leeds, BFD, He et al. 2022), containing 64,000+ individual human judgments.

For each pair i, let ΔVᵢ = human visual difference, ΔEᵢ = predicted distance. STRESS finds the optimal scale F minimizing residuals:

STRESS = 100 × √( Σ(ΔEᵢ − F·ΔVᵢ)² / Σ(ΔEᵢ)² )

Scale: 0 = perfect, 100 = no correlation. Full methodology: arXiv:2602.23010.

Gradient Quality (GenSpace)

Helmlab GenSpace vs OKLab — head-to-head on ColorBench (90 metrics, 3,038 gradient pairs across sRGB, Display P3, and Rec.2020 gamuts):

Category GenSpace wins OKLab wins Tie
Gamut geometry 24 0 3
Application 8 1 3
Independent (Hung-Berns, Ebner-Fairchild, Pointer) 6 1 0
Gradient quality 5 3 3
Perceptual accuracy 5 0 0
Structural 4 2 2
Achromatic 2 0 0
Advanced 2 0 4
Hue 2 0 0
Special 2 1 0
Accessibility 1 1 0
Banding 1 0 1
Numerical stability 0 0 3
Total 62 9 19

Gradient Uniformity

CV (coefficient of variation of CIEDE2000 step sizes). Lower is better.

Method Red→Blue Orange→Cyan Black→White Technique
Helmlab gradient() ≈ 0% ≈ 0% ≈ 0% arc-length reparam.
Helmlab GenSpace 30.3% 26.5% 40.7% linear interpolation
Oklab 31.5% 41.4% 41.2% linear interpolation
CIE Lab 44.8% 52.3% 61.5% linear interpolation

Note: gradient() achieves ≈ 0% via CIEDE2000 arc-length reparameterization. This redistributes steps to equal perceptual spacing — an algorithm that could be applied to any space. Helmlab ships it built-in.

Project Structure

src/helmlab/
├── helmlab.py              # Main API (Helmlab class)
├── spaces/
│   ├── metric.py           # MetricSpace — 72-param enriched pipeline
│   ├── gen.py              # GenSpace — depcubic + enrichment pipeline
│   ├── base.py             # Abstract base class
│   └── ...                 # 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 + adaptive clipping)
│   └── ...                 # Converters, I/O, visualization
├── data/
│   ├── metric_params.json  # MetricSpace params (v21, STRESS 22.48 w/ Bradford CAT)
│   ├── gen_params.json     # GenSpace params (v0.11.1, depcubic + enrichment)
│   └── ...                 # Dataset loaders (COMBVD, Munsell, etc.)
├── export.py               # Token export (CSS, Android, iOS, Tailwind)
└── feedback/               # Human feedback collection tools

packages/helmlab-js/        # npm package (TypeScript)
packages/postcss-helmlab/   # PostCSS plugin
tests/                      # 588 tests (336 Python + 252 JavaScript)

# ColorBench (the 90-metric evaluation suite) lives in its own repo:
# https://github.com/Grkmyldz148/colorbench

Tests

python -m pytest tests/ -q              # 336 Python tests (334 pass + 2 skip)
cd packages/helmlab-js && npx vitest run # 252 JS tests

AI skill: color-space routing

There is no perfect color space — but there is a right one per task. skills/color-space-routing packages our benchmark evidence as a drop-in skill for Claude Code / Cursor / any AI assistant: task → space routing table, measured numbers (including where each space loses), copy-paste recipes, and a pitfall checklist.

Research

The optimization experiments, checkpoints, and analysis scripts that led to the current GenSpace v0.11.1 are available in a separate repository:

helmlab-experimental — 480+ experiments across 4 transfer functions, 3 M₁ variants, and systematic grid searches. Includes all checkpoints, optimization scripts, and the full experiment report.

Citation

@article{yildiz2026helmlab,
  title={Helmlab: A Two-Space Family of Analytical, Data-Driven Color Spaces for UI Design Systems},
  author={Y{\i}ld{\i}z, G{\"o}rkem},
  journal={arXiv preprint arXiv:2602.23010},
  year={2026},
  url={https://arxiv.org/abs/2602.23010}
}

Author

Gorkem Yildizhelmlab.space

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

helmlab-1.0.0.tar.gz (116.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

helmlab-1.0.0-py3-none-any.whl (93.8 kB view details)

Uploaded Python 3

File details

Details for the file helmlab-1.0.0.tar.gz.

File metadata

  • Download URL: helmlab-1.0.0.tar.gz
  • Upload date:
  • Size: 116.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for helmlab-1.0.0.tar.gz
Algorithm Hash digest
SHA256 4626bcf022210d82cb7415d3aaaf8dd99d837eced54300a3d2decfbf7fabe219
MD5 ab0b76df146eebbbc9eb45c9634d48b4
BLAKE2b-256 3fa233c48a857dbe1f6e7e4038c66115b5df056059384ee652f181e3f8e901d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for helmlab-1.0.0.tar.gz:

Publisher: deploy.yml on Grkmyldz148/helmlab

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file helmlab-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: helmlab-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 93.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for helmlab-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2c1aa1cd6905b19235b2de16de9cf7a7c86b4be5ec67f31607ed64f795530b57
MD5 3f4d456bdb7a5973fcee1df2aaff6b58
BLAKE2b-256 b87fe496b61068f0dac778db948fa191e12ac12d60dd59ddf6fc666f51cacec2

See more details on using hashes here.

Provenance

The following attestation bundles were made for helmlab-1.0.0-py3-none-any.whl:

Publisher: deploy.yml on Grkmyldz148/helmlab

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

0.17.0

2 files

0.16.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.0

2 files

0.12.2

2 files

0.12.1

2 files

0.12.0

2 files

0.11.9

2 files

0.11.8

2 files

0.11.7

2 files

0.11.6

2 files

0.11.5

2 files

0.11.4

2 files

0.11.3

2 files

0.11.2

2 files

0.11.0

2 files

0.10.1

2 files

0.10.0

2 files

0.9.2

2 files

0.9.1

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.4

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page