Tool-agnostic LUT and colormap management for Python
Project description
lutopia
Tool-agnostic LUT and colormap management for Python.
Lutopia treats every palette — smooth gradient or legacy 256-step table — as a single unified continuous function. One API, zero fragmentation across visualization ecosystems.
import lutopia as lt
# Matplotlib
from matplotlib.colors import ListedColormap
cmap = ListedColormap(lt.viridis.plt)
# Seaborn
sns.heatmap(data, cmap=lt.viridis.sns)
# Plotly
fig.update_traces(colorscale=lt.viridis.plotly)
Features
- 297 palettes out of the box — matplotlib's full catalog + the entire colorcet scientific collection
- Unified engine — smooth gradients and legacy step-function LUTs share one interface
- Zero visualization dependencies — runtime package requires only
numpyandscipy - Native consumer outputs —
.plt,.mpl,.sns,.plotlyreturn exactly what each library expects, no adapters needed - Interactive palette picker —
uvx lutopiaopens a live GUI browser with one-click code generation srclayout,uv_buildbackend — modern packaging, ships a clean wheel
Installation
pip install lutopia
# or
uv add lutopia
Quick Start
import lutopia as lt
# List all available palettes
print(dir(lt)) # ['accent', 'afmhot', 'autumn', ..., 'viridis', ...]
# Sample raw float values (N × 3 array, values in [0, 1])
arr = lt.viridis.sample(256) # numpy array, shape (256, 3)
# Get hex strings
hexes = lt.plasma.to_hex_list(64) # ['#0d0887', '#2d0594', ...]
Consumer Properties
Every palette exposes three ready-to-use consumer properties. No third-party imports are required by the library itself.
Matplotlib
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
import lutopia as lt
cmap = ListedColormap(lt.inferno.plt)
plt.imshow(data, cmap=cmap)
plt.colorbar()
.plt / .mpl / .matplotlib all return the same (256, 3) float64 NumPy array that ListedColormap and LinearSegmentedColormap accept directly.
Seaborn
import seaborn as sns
import lutopia as lt
sns.heatmap(data, cmap=lt.magma.sns)
.sns / .seaborn return a list of 256 hex strings, which Seaborn accepts for both palette= and cmap= arguments.
Plotly
import plotly.graph_objects as go
import lutopia as lt
fig = go.Figure(go.Heatmap(z=data, colorscale=lt.turbo.plotly))
.plotly returns a native Plotly colorscale — a list of [fraction, "#rrggbb"] pairs spanning [0.0, 1.0].
Palette Browser
The interactive palette picker is available as an ephemeral tool — no install needed:
uvx lutopia
# or, if already installed:
lutopia
A tkinter window opens showing all 297 palettes as color swatches. Click any palette to open a code snippet dialog:
- Choose your target ecosystem (Matplotlib, Seaborn, Plotly, or Raw Hex)
- Copy the generated snippet directly to your clipboard
Available Palettes
Lutopia ships with palettes sourced from:
| Source | Count | Examples |
|---|---|---|
| Matplotlib | ~90 | viridis, plasma, inferno, magma, cividis, jet, hot, coolwarm, spectral, tab10 |
| Colorcet | ~200 | fire, rainbow4, bmy, bgyw, isolum, gouldian, kbc, dimgray |
All palettes are available immediately after install — no scraping, no network calls.
How It Works
All palettes are stored as compact JSON anchor files in lutopia/palettes/. A continuous UnifiedPalette engine evaluates them on demand:
- Linear interpolation for smooth gradient maps (e.g. viridis, plasma)
- Nearest-neighbor / step for discrete legacy tables (e.g. ImageJ
.lutfiles)
{
"name": "viridis",
"interpolation": "linear",
"anchors": [
[0.0, [68, 1, 84]],
[0.5, [33, 145, 140]],
[1.0, [253, 231, 37]]
]
}
Palettes are loaded lazily on first access and cached for the lifetime of the interpreter session.
Development
Setup
git clone https://github.com/bryanbarcelona/lutopia.git
cd lutopia
uv sync
Tooling
uv run ruff check . # lint
uv run ruff format . # format
uv run ty check src/lutopia # type check
uv run pytest # tests
Adding Palettes
From matplotlib / colorcet:
uv run python scripts/scrape_ecosystems.py
Reads upstream colormap libraries, reduces continuous maps to sparse anchor points (max error < 1/255), and writes JSON assets to src/lutopia/palettes/. Run with --overwrite to force regeneration.
From a binary ImageJ / Fiji .lut file:
uv run python scripts/parse_legacy_lut.py path/to/fire.lut [name]
Parses the standard 768-byte RGB block and writes a step-interpolation JSON asset.
After adding palettes, commit the new JSON files and they will be included in the next release.
Releasing
Releases are fully automated via CI. Every merge to main triggers:
- Commitizen bumps the version and generates a changelog entry
uv buildproduces the wheel and sdistuv publishpushes to PyPI via trusted publishing (OIDC, no API keys)- A GitHub Release is created and tagged
Commit messages must follow Conventional Commits:
cz commit
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lutopia-0.2.0.tar.gz.
File metadata
- Download URL: lutopia-0.2.0.tar.gz
- Upload date:
- Size: 115.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd4164a5b9099214253489d4e97565872dc78d1a784fad6b191fa062da474539
|
|
| MD5 |
c894f6f46567d38c4d117cc0ac81fd22
|
|
| BLAKE2b-256 |
6346ae6d25d74f703067d2868fd9868a4f701ccbb523f129a9b280ee8cdb4f80
|
File details
Details for the file lutopia-0.2.0-py3-none-any.whl.
File metadata
- Download URL: lutopia-0.2.0-py3-none-any.whl
- Upload date:
- Size: 218.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb8ac225921cae019d4175ce642e16d7682711aab0f6d1de776e2b3f78904255
|
|
| MD5 |
ed8118021d4a5462caa5ae6664f1a16c
|
|
| BLAKE2b-256 |
51053d114a673643faeb3a94d3d604963fd676bf2b11b00bd4da1f576e6b7190
|