Melanopy¶
A melanopic (circadian) axis for scientific colormaps.
Colormaps are usually judged on two axes — perceptual uniformity and colour-vision-deficiency (CVD) safety. Melanopy adds a third: how much short-wavelength, melanopic (melatonin-suppressing) light a map emits. Unlike the other two it is a design dimension you choose by context, not a pass/fail gate — a sleep lab wants the protective end of the axis, a daytime alerting display the other.
The package measures the axis (a rater that scores any colormap, display white = 1.0), generates a one-parameter family that walks it while holding uniformity and CVD-safety fixed, and ships CVD-safe named colormaps.

Scope — a colour property, not a dose
Melanopy rates a colour's chromaticity, not light dose. Real circadian load also depends on brightness, screen fill, viewing distance, and ambient light; if you need to stay alert the dominant lever is room lighting. The concept, validation, and limitations are covered in full in the manuscript — these docs stay focused on the API.
Install¶
Quickstart¶
import matplotlib.pyplot as plt
import numpy as np
import melanopy as mp
# Score any colormap on the melanopic axis (display white = 1.0)
c = plt.get_cmap("viridis")(np.linspace(0, 1, 256))[:, :3]
print(mp.rate_colormap(c))
# {'melanopic_ratio': 0.834, 'mp_spread': 0.556, 'range': (0.395, 3.069)}
# Use the named endpoints (registered with matplotlib) on any 2-D field Z
mp.register()
Z = np.add.outer(np.linspace(0, 1, 200), np.linspace(0, 1, 200))
plt.imshow(Z, cmap="sodium") # protective: warm, low-melanopic
plt.imshow(Z, cmap="xenon") # alerting: cool, high-melanopic
plt.imshow(Z, cmap="equilux") # circadian-neutral (M/P ≈ 1)
# Dial the whole axis: alpha 0 (protective) .. 1 (alerting)
cmap = mp.circadia(0.3, as_cmap=True)
melanopic_ratio < 1 → protective (warm); > 1 → alerting (cool/blue).
The two metrics¶
rate_colormap returns two distinct numbers:
| metric | what it tells you |
|---|---|
M/P mean (melanopic_ratio) |
where a map sits on the axis (display white = 1) |
M/P spread (σ) (mp_spread) |
how tightly it sits — a tight spread reads as a "pure" ramp |
A map can be mildly protective on average yet smeared (viridis dumps blue at its dark end); the two numbers tell that apart.
Where next¶
- API reference — the public functions and named colormaps, with examples.
- Cookbook — short, copy-pasteable recipes with output.