Skip to main content

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 numpy and scipy
  • Native consumer outputs — .plt, .mpl, .sns, .plotly return exactly what each library expects, no adapters needed
  • Interactive palette picker — uvx lutopia opens a live GUI browser with one-click code generation
  • src layout, uv_build backend — 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 .lut files)
{
  "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:

  1. Commitizen bumps the version and generates a changelog entry
  2. uv build produces the wheel and sdist
  3. uv publish pushes to PyPI via trusted publishing (OIDC, no API keys)
  4. A GitHub Release is created and tagged

Commit messages must follow Conventional Commits:

cz commit

License

MIT

Metadata

Release files for lutopia 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lutopia 0.2.0
File Size Uploaded
lutopia-0.2.0.tar.gz 115.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lutopia 0.2.0
File Interpreter ABI Platform
lutopia-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 333.5 kB

Release files / lutopia-0.2.0.tar.gz

Download URL lutopia-0.2.0.tar.gz
Size 115.4 kB
Tags Source
SHA-256 checksum
How to use checksums
cd4164a5b9099214253489d4e97565872dc78d1a784fad6b191fa062da474539
BLAKE2b-256 checksum
How to use checksums
6346ae6d25d74f703067d2868fd9868a4f701ccbb523f129a9b280ee8cdb4f80
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / lutopia-0.2.0-py3-none-any.whl

Download URL lutopia-0.2.0-py3-none-any.whl
Size 218.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fb8ac225921cae019d4175ce642e16d7682711aab0f6d1de776e2b3f78904255
BLAKE2b-256 checksum
How to use checksums
51053d114a673643faeb3a94d3d604963fd676bf2b11b00bd4da1f576e6b7190
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page