Metadata-Version: 2.4
Name: datahues
Version: 0.1.1
Summary: Generate perceptually uniform colour ramps for data visualisation.
Keywords: python,data,visualization,visualisation,color,color
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.17
Requires-Dist: matplotlib>=3.3
Dynamic: license-file

# `datahues`

**Generate perceptually uniform colour ramps for data visualisation.**

[![Test](https://github.com/aneeshnaik/datahues/actions/workflows/test.yaml/badge.svg)](https://github.com/aneeshnaik/datahues/actions/workflows/test.yaml)
[![Coverage Status](https://coveralls.io/repos/github/aneeshnaik/datahues/badge.svg?branch=main)](https://coveralls.io/github/aneeshnaik/datahues?branch=main)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/aneeshnaik/datahues/blob/main/LICENSE)


## Overview

`datahues` creates smooth, [perceptually uniform](https://en.wikipedia.org/wiki/Color_appearance_model) colour gradients from a start colour to an end colour. Unlike simple RGB or HSL interpolation, which can produce visually uneven ramps, this library leverages the [**Oklab colour space**](https://en.wikipedia.org/wiki/Oklab_color_space): a perceptually uniform space where equal mathematical changes correspond to equal perceptual colour differences.

![Comparison of RGB vs Oklab interpolation](README_assets/ramp_comparison.png)

*A comparison of a linear RGB colour ramp (generated with `matplotlib`'s `LinearSegmentedColormap.from_list`) versus an Oklab-interpolated ramp generated by `datahues`. The start and end colours here are #F61212 ("Pure Red") and #12F612 ("Lime").*

The figure above demonstrates why it's important to think about perceptual uniformity of colour ramps. If you naïvely interpolate in RGB space between two colours, you end up with a ramp that gives you artificial banding (cf. left panel). You might then see patterns in your data that aren't truly there!

## Installation

`datahues` is available on [PyPI](https://pypi.org/project/datahues/) and [conda-forge](https://anaconda.org/channels/conda-forge/packages/datahues/overview).

Install from PyPI with `pip`:
```bash
pip install datahues
```

Install from `conda-forge` with `conda`, setting the `conda-forge` channel:
```bash
conda install -c conda-forge datahues
```

## Core Functions

`datahues` just has two public functions: `generate_hex_list` and `generate_cmap`. Both generate a sequential colour ramp given start and end colour hexes. The former returns a list of hexes, and the latter returns a `matplotlib` `LinearSegmentedColormap` object.

### `generate_hex_list(start_hex, end_hex, n_stops=512)`

Between start and end colours, generates a list of hex colour codes representing points along a smooth colour ramp. It is assumed the user wants a discrete number (`n_stops`) of points, so no warning is given when `n_stops` is small (unlike in `generate_cmap` below). However, if these hexes are being used to create a continuous colour ramp, it is recommended to use `n_stops`>=128.

- **Parameters:** 
  - `start_hex`: Starting colour as hex code (e.g., `"#FF0000"`)
  - `end_hex`: Ending colour as hex code (e.g., `"#0000FF"`)
  - `n_stops`: Number of colour stops in the ramp (default: 512)
- **Returns:** List of hex colour codes representing the gradient

### `generate_cmap(start_hex, end_hex, n_stops=512, name="interp_ramp")`

Betweem start and end colours, creates a `matplotlib` `LinearSegmentedColormap` object, forming a smooth colour ramp.

- **Parameters:**
  - `start_hex`, `end_hex`, `n_stops`: As above
  - `name`: The "name" of the colour ramp for matplotlib internal purposes (default: "interp_ramp")
- **Returns:** `LinearSegmentedColormap` object ready to use in matplotlib visualisation
- **Warning:** `n_stops < 128` may produce visible banding; use larger values for smoother results


## How It Works

The library converts colours through multiple colour spaces to achieve perceptual uniformity:

1. **Hex → RGB** — Parse hex codes into normalised [0.0, 1.0] RGB values
2. **RGB → XYZ** — Apply gamma correction and convert to CIE XYZ (D65 illuminant)
3. **XYZ → Oklab** — Convert through LMS intermediate space to Oklab (perceptually uniform)
4. **Interpolate in Oklab** — Create evenly-spaced values in perceptual space
5. **Oklab → RGB → Hex** — Reverse conversion back to hex color codes

This approach ensures that visual transitions between colours feel smooth and natural across the entire gradient.

## Future Features

The list below has some ideas for future features to be implemented in `datahues`. No promises!

- Colour sequences with more than 2 colours.
- Alternative colour spaces (beyond Oklab)
- Alternative input types (besides hex codes), e.g. matplotlib colour names or RGB tuples.

Feel free to get in touch / make an issue with other requests.
