Skip to content

Add check_palette() for colorblind accessibility #2

@truenomad

Description

@truenomad

Summary

sntutils has 27+ built-in palettes used for choropleth maps (get_palette(), auto_bin()), but zero colorblind accessibility checks. ~8% of men have some form of color vision deficiency. We need a function that checks if a palette is safe and optionally fixes it.

Proposed function

check_palette(
  palette,
  n = NULL,
  fix = FALSE,
  severity = 1,
  tolerance = 10
)

Parameters

Param Type Default Description
palette character required Preset name (e.g. "blues") or hex vector
n integer NULL Number of colors to check (passed to get_palette())
fix logical FALSE If TRUE, return an adjusted colorblind-safe palette
severity numeric 1 Deficiency severity 0–1 (1 = complete)
tolerance numeric 10 Min perceptual distance threshold (Delta E in CIELab)

Return value

A list with:

  • safe — logical, TRUE if palette passes all 3 deficiency types
  • colors — the input palette (hex vector)
  • min_dist — named numeric vector with min pairwise distance for each type + normal
  • details — data frame with per-type results (type, min_dist, pass)
  • fixed — (only when fix = TRUE) adjusted hex vector that passes the check

Core logic

Checking:

  1. Resolve palette via get_palette(palette, n) to get hex vector
  2. For each deficiency type (deutan, protan, tritan):
    a. Simulate with colorspace::deutan(), protan(), tritan()
    b. Convert simulated colors to CIELab
    c. Compute all pairwise Euclidean distances in Lab space
    d. Record minimum distance
  3. If all min distances >= tolerance → safe = TRUE

Fixing (when fix = TRUE):

  1. Convert input palette to HCL space
  2. Keep the hue endpoints (preserve color intent)
  3. Spread luminance values evenly from ~30 to ~90
  4. Rebuild palette with colorspace::hex(colorspace::polarLUV(L, C, H))
  5. Re-check — if still fails, reduce chroma and widen luminance further
  6. If that still fails, fall back to colorspace::sequential_hcl(n, palette = "viridis") and warn

Dependency: colorspace

Add to Imports. Provides CVD simulation, HCL conversion, and desaturation — one package handles both checking and fixing.

Files to create/modify

File Action
R/check_palette.R Create — new function + internal helpers
tests/testthat/test-check_palette.R Create — tests
DESCRIPTION Edit — add colorspace to Imports

Example usage

# check a built-in palette
check_palette("blues", n = 6)

# check custom colors
check_palette(c("#FF0000", "#00FF00", "#0000FF"))

# check and fix
result <- check_palette("reds", n = 5, fix = TRUE)
result$safe
result$fixed

# check with partial severity
check_palette("default", n = 6, severity = 0.5)

Tests to write

  1. Known-safe palette (viridis) returns safe = TRUE
  2. Known-bad palette (red + green only) returns safe = FALSE
  3. fix = TRUE returns a palette that passes the check
  4. Custom hex input works
  5. Preset name input works (resolves via get_palette())
  6. n parameter interpolates correctly before checking
  7. severity = 0 always returns safe (no deficiency)
  8. Edge cases: single color, two colors
  9. Tolerance parameter affects pass/fail threshold
  10. Error on invalid inputs (missing palette, bad severity, bad tolerance)

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions