API reference¶
The public API is curated in melanopy.__all__. Everything below is importable directly from the
top-level package, e.g. import melanopy as mp; mp.rate_colormap(...).
Rating¶
rate_colormap ¶
Rate an sRGB ramp on the melanopic axis (display white = 1.0).
Both summary numbers are luminance-weighted and ignore near-black pixels (which emit almost nothing), so neither is dominated by the dark end of the ramp.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
colors
|
array - like
|
An |
required |
panel
|
str
|
Display archetype selecting the per-primary coefficients (see :data: |
'representative'
|
profile
|
bool
|
When |
False
|
Returns:
| Type | Description |
|---|---|
dict
|
|
Examples:
melanopic_ratio ¶
Melanopic ratio (M/P) of one or more sRGB colours, normalized so display white = 1.0.
< 1 is protective (warm, low melatonin drive); > 1 is alerting (cool, blue-rich).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rgb
|
array - like
|
A single |
required |
panel
|
str
|
Display archetype selecting the per-primary coefficients (see :data: |
'representative'
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The melanopic ratio per input colour. |
Examples:
circadia_rating ¶
Rated melanopic ratio of a Circadia map at alpha — the physical number behind the dial.
alpha is a geometric position on the OKLab morph, not a melanopic ratio, and the M/P a
viewer actually receives is panel-dependent. This composes the generator and the rater so a
live UI (e.g. a labelled slider) can show the rated M/P for its configured panel rather
than bare alpha. The recompute is cheap (a vectorized 256-point rating); a hot UI may
memoize on (round(alpha, 3), panel).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
alpha
|
float
|
Position on the Circadia axis in |
required |
panel
|
str
|
Display archetype selecting the per-primary coefficients (see :data: |
'representative'
|
Returns:
| Type | Description |
|---|---|
tuple of float
|
|
Examples:
Generator — the Circadia family¶
circadia ¶
One member of the Circadia family — a perceptually-uniform, CVD-safe ramp at dial alpha.
alpha sets the warm→cool colour temperature: 0 is protective (Sodium, warm, low
melanopic), 1 is alerting (Xenon, cool, high melanopic), and ~0.55 is the M/P ≈ 1
crossover. It is the design input; read the emergent melanopic ratio back with
:func:circadia_rating or :func:rate_colormap.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
alpha
|
float
|
Position on the Circadia axis in |
required |
n
|
int
|
Number of samples in the ramp. |
256
|
as_cmap
|
bool
|
Return a :class: |
False
|
name
|
str
|
Name for the colormap when |
None
|
Returns:
| Type | Description |
|---|---|
ndarray or ListedColormap
|
An |
Examples:
circadian_cmap is an alias of circadia.
circadia_sweep ¶
Full-axis sequential map sweeping protective (Sodium, warm) -> alerting (Xenon, cool), with
the melanopic ratio rising ~linearly along the ramp -- the "data axis is the melanopic axis"
teaching map. The shared monotone OKLab lightness keeps it ordered and CVD-recoverable; the
positions are calibrated against the rater so M/P is linear in the data value. This is the one
melanopic-aware generator (via a local import); circadia itself stays pure OKLab geometry.
Examples:
circadia_diverging ¶
Diverging map for signed data: warm Sodium (protective, M/P<1) <- light neutral centre (M/P=1) -> cool Xenon (alerting, M/P>1). Each arm has monotone lightness, but -- like most diverging maps -- the arms are told apart across zero by hue, so it is NOT CVD-order-recoverable; use the sequential maps where CVD-safety matters.
Examples:
The named anchors SODIUM (alpha=0.0), EQUILUX (alpha=0.55, the M/P = 1 crossover),
and XENON (alpha=1.0) are exported as ready-made matplotlib.colors.ListedColormap objects.
matplotlib integration¶
register ¶
Register sodium/xenon/equilux + circadia_sweep/circadia_diverging as matplotlib colormaps.
After calling this, the maps are available by name to any matplotlib call. Safe to call more than once.
Examples:
Categorical palette¶
The CVD-safe categorical palette is exposed as CATEGORICAL (a ListedColormap), with the raw hex
lists CATEGORICAL_DARK / CATEGORICAL_LIGHT and CATEGORICAL_NAMES. One palette serves every
circadian regime: small categorical marks emit negligible light.
>>> import melanopy as mp
>>> mp.CATEGORICAL_NAMES
['amber', 'sky', 'teal', 'yellow', 'blue', 'vermillion', 'rose']
>>> mp.CATEGORICAL_DARK[:3]
['#F2A036', '#81CAF0', '#009C89']
Adding a measured panel¶
The built-in panels (representative, led_lcd, oled, wide_gamut) are spectral archetypes,
not measurements — so a reported M/P is indicative, not metrological. The protective ↔ alerting
ranking is stable across panels (Spearman ρ ≥ 0.99), so relative comparisons hold on any panel;
only the absolute M/P needs a measured one.
For research-grade work, measure the three primary SPDs (R, G, B at full drive) on the package's
1 nm grid (melanopy.spectra.WL, 380–780 nm) and derive the coefficients:
>>> from melanopy.spectra import coefficients_from_primaries
>>> coeffs = coefficients_from_primaries({"R": spd_r, "G": spd_g, "B": spd_b}) # doctest: +SKIP
Add the result to melanopy.coeffs.PANELS as a new keyed row (e.g. "lab_monitor": {...}); the
panel="lab_monitor" argument then threads through rate_colormap, melanopic_ratio, and
circadia_rating.
coefficients_from_primaries ¶
Derive the three per-primary M/P coefficients from measured primary SPDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
primaries
|
dict
|
|
required |
smel
|
array - like
|
Override the melanopic action spectrum / V(λ); default to the shipped CIE tables. |
None
|
vlam
|
array - like
|
Override the melanopic action spectrum / V(λ); default to the shipped CIE tables. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
|
Examples: