colormap

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package colormap provides a matplotlib-style colormap and color-scale API for the ggplot grammar of graphics pipeline.

Core abstractions

Categories

Cmaps are grouped into matplotlib's standard categories:

  • PerceptuallyUniform: viridis, plasma, inferno, magma, cividis, turbo
  • Sequential: greys, blues, greens, oranges, reds, purples, ylgn, ylgnbu, ylorbr, ylorrd, bugn, gnbu, bupu, orrd, pubu, pubugn, purd, rdpu
  • Diverging: rdbu, rdylbu, spectral, coolwarm, brbg, piyg, prgn, puor, rdgy, rdylgn, bwr
  • Cyclic: twilight, twilight_shifted, hsv
  • Qualitative: tab10, tab20, set1, set2, set3, paired, pastel1, pastel2, accent, dark2, okabe_ito

Registry

Built-in cmaps register themselves at init time. Look them up by name with Resolve (the suffix "_r" returns the reversed colormap, e.g. "viridis_r"):

cm, err := colormap.Resolve("viridis")
cm := colormap.MustResolve("plasma_r")

or use the typed exported variables directly:

cm := colormap.Viridis
cm := colormap.Plasma.Reversed()

Color literal parsing

Parse accepts hex strings (delegates to gg.ParseHex), CSS / X11 named colors, the matplotlib "tab:blue" / "tab:orange" aliases, and rgb()/rgba()/ hsl() functional forms. It returns gg.RGBA (float-space color) so the result interoperates directly with the renderer without uint8 truncation.

Design conventions

All Cmap methods return gg.RGBA (not image/color.Color) so the rendering pipeline can stay in float space. gg.RGBA itself satisfies the standard color.Color interface, so values pass through canvas.SetColor unchanged.

LUT data is vendored from matplotlib's BSD/CC0 reference data. The package does not reimplement hex parsing or RGB lerping — those come from gg.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MustParse

func MustParse(s string) gg.RGBA

MustParse is like Parse but panics on error.

func MustRegister

func MustRegister(c Cmap)

MustRegister registers c and panics on error. Intended for init-time use.

func Names

func Names() []string

Names returns all registered cmap names sorted alphabetically. The "_r" reversed forms are not enumerated — they are derivable from each base name.

func NamesByCategory

func NamesByCategory(cat Category) []string

NamesByCategory returns the registered cmap names whose Category matches the argument, sorted alphabetically.

func Parse

func Parse(s string) (gg.RGBA, error)

Parse converts a color literal to gg.RGBA. Accepted forms:

  • Hex: "#RGB", "#RGBA", "#RRGGBB", "#RRGGBBAA" (delegates to gg.ParseHex; leading '#' optional).
  • CSS / X11 named colors: "red", "coral", "rebeccapurple", … (147 names).
  • Matplotlib aliases: "tab:blue", "tab:orange", … through "tab:cyan".
  • Functional rgb / rgba: "rgb(255,0,0)", "rgba(0,128,0,0.5)". Channels accept 0–255 integers or "<n>%" (0–100).
  • Functional hsl: "hsl(120,100%,50%)" — h in degrees [0,360), s and l in percent.

Empty strings return an error. Comparisons are case-insensitive for named colors and the leading function keyword.

func ParseRGB

func ParseRGB(spec string, defR, defG, defB float64) (r, g, b float64)

ParseRGB parses a color spec and returns its normalized [0,1] RGB components. On empty or invalid input, defR/defG/defB are returned unchanged.

func Register

func Register(c Cmap) error

Register adds a Cmap to the global registry under its Name. Registration is idempotent for the exact same Cmap value, but registering a different Cmap under an already-taken name returns an error.

Names are looked up case-insensitively; the canonical form is lowercase.

Types

type AsinhNorm

type AsinhNorm struct {
	LinearWidth float64
	Vmin, Vmax  float64
	// contains filtered or unexported fields
}

AsinhNorm performs a smooth asinh (inverse-hyperbolic-sine) transform that behaves linearly near zero and logarithmically far from zero — useful for data spanning many decades that includes zeros or negatives.

func (*AsinhNorm) Bounds

func (n *AsinhNorm) Bounds() (float64, float64)

func (*AsinhNorm) Inverse

func (n *AsinhNorm) Inverse(t float64) float64

func (*AsinhNorm) Norm

func (n *AsinhNorm) Norm(v float64) float64

func (*AsinhNorm) Train

func (n *AsinhNorm) Train(col dataset.AnyColumn) error

type BoundaryNorm

type BoundaryNorm struct {
	Boundaries []float64 // ascending; len >= 2
	Ncolors    int       // typically len(Boundaries)-1
	Clip       bool      // clamp out-of-range to nearest boundary
}

BoundaryNorm bins v into one of len(Boundaries)-1 cells. The result is rounded to one of Ncolors discrete fractions so a Cmap.Resampled(Ncolors) produces a stepped colorbar with breakpoints at Boundaries.

func (*BoundaryNorm) Bounds

func (n *BoundaryNorm) Bounds() (float64, float64)

func (*BoundaryNorm) Inverse

func (n *BoundaryNorm) Inverse(t float64) float64

func (*BoundaryNorm) Norm

func (n *BoundaryNorm) Norm(v float64) float64

func (*BoundaryNorm) Train

func (n *BoundaryNorm) Train(col dataset.AnyColumn) error

Train is a no-op: BoundaryNorm bounds are user-specified.

type Category

type Category int

Category groups colormaps along matplotlib's standard taxonomy. Used by Cmap.Category and NamesByCategory.

const (
	// Sequential covers smooth, monotonic-lightness colormaps suitable for
	// continuous, ordered data without a natural midpoint (Blues, Reds, ...).
	Sequential Category = iota
	// PerceptuallyUniform colormaps preserve the perception of equal data
	// differences across the range (viridis, plasma, inferno, magma, cividis).
	PerceptuallyUniform
	// Diverging colormaps emphasize departure from a meaningful midpoint
	// (RdBu, Spectral, ...).
	Diverging
	// Cyclic colormaps wrap (twilight, hsv).
	Cyclic
	// Qualitative covers discrete categorical palettes (tab10, Set1, ...).
	Qualitative
	// Miscellaneous holds everything that doesn't fit cleanly elsewhere
	// (turbo, terrain, etc.).
	Miscellaneous
)

func (Category) String

func (c Category) String() string

type Cmap

type Cmap interface {
	// At samples the colormap at t. t outside [0,1] is clamped (or replaced
	// by Under/Over). NaN inputs return Bad.
	At(t float64) gg.RGBA

	// Name returns the registered identifier.
	Name() string

	// N returns the number of distinct colors. 256 for LUT-backed cmaps,
	// len(colors) for [ListedCmap].
	N() int

	// Category returns the matplotlib taxonomy bucket.
	Category() Category

	// Reversed returns a Cmap with the gradient flipped (At(t) -> At(1-t)).
	Reversed() Cmap

	// Resampled returns a Cmap that quantizes t into n equally-sized bins.
	// Useful for legend swatches or stepped color bars.
	Resampled(n int) Cmap

	// WithExtremes returns a Cmap with explicit colors for out-of-range and
	// NaN inputs. Pass nil for any to keep the default (clamped At(0)/At(1)
	// for under/over, transparent for bad).
	WithExtremes(under, over, bad *gg.RGBA) Cmap
}

Implementations should:

  • Clamp t outside [0,1] to At(0)/At(1), or substitute Under/Over if set via WithExtremes.
  • Return Bad (or fully-transparent black) when t is NaN.
  • Be safe for concurrent reads — Cmap values are immutable; mutators (Reversed, Resampled, WithExtremes) return a new Cmap.
var (
	// PerceptuallyUniform — matplotlib defaults.
	Viridis Cmap
	Plasma  Cmap
	Inferno Cmap
	Magma   Cmap
	Cividis Cmap

	// Sequential — ColorBrewer 9-class.
	Greys   Cmap
	Blues   Cmap
	Greens  Cmap
	Oranges Cmap
	Reds    Cmap
	Purples Cmap
	YlGn    Cmap
	YlGnBu  Cmap
	YlOrBr  Cmap
	YlOrRd  Cmap

	// Diverging — ColorBrewer 11-class + matplotlib originals.
	RdBu     Cmap
	RdYlBu   Cmap
	RdYlGn   Cmap
	Spectral Cmap
	BrBG     Cmap
	PiYG     Cmap
	PRGn     Cmap
	PuOr     Cmap
	RdGy     Cmap
	Coolwarm Cmap
	Bwr      Cmap

	// Qualitative.
	Tab10    Cmap
	Tab20    Cmap
	Tab20b   Cmap
	Tab20c   Cmap
	Set1     Cmap
	Set2     Cmap
	Set3     Cmap
	Paired   Cmap
	Pastel1  Cmap
	Pastel2  Cmap
	Accent   Cmap
	Dark2    Cmap
	OkabeIto Cmap
)

func MustResolve

func MustResolve(name string) Cmap

MustResolve is like Resolve but panics on error.

func Resolve

func Resolve(name string) (Cmap, error)

Resolve looks up a Cmap by name (case-insensitive). Names with the suffix "_r" return the reversed form of the base colormap, matching matplotlib's convention. Returns an error for unknown names.

type Color

type Color = gg.RGBA

Color is the canonical color type used throughout this package. It is a type alias for gg.RGBA (float-space components in [0,1] plus alpha), so user code can refer to colormap.Color without importing gg directly. The alias keeps the rendering pipeline in float space — no uint8 truncation when sampling or interpolating colormaps.

type LinearNorm

type LinearNorm struct {
	Vmin, Vmax float64
	// contains filtered or unexported fields
}

LinearNorm scales v linearly between Vmin and Vmax. Zero value is valid: it auto-trains on the first Train() call.

func (*LinearNorm) Bounds

func (n *LinearNorm) Bounds() (float64, float64)

func (*LinearNorm) Inverse

func (n *LinearNorm) Inverse(t float64) float64

func (*LinearNorm) Norm

func (n *LinearNorm) Norm(v float64) float64

func (*LinearNorm) Train

func (n *LinearNorm) Train(col dataset.AnyColumn) error

type LinearSegmentedCmap

type LinearSegmentedCmap struct {
	// contains filtered or unexported fields
}

LinearSegmentedCmap is a continuous colormap backed by a 256-entry RGB LUT. It is the standard backing type for matplotlib's perceptually-uniform, sequential, diverging, and cyclic colormaps.

func NewLinearSegmented

func NewLinearSegmented(name string, cat Category, lut [256][3]uint8) *LinearSegmentedCmap

NewLinearSegmented constructs a colormap from a 256-entry LUT.

func (*LinearSegmentedCmap) At

At samples the colormap by linearly interpolating between adjacent LUT entries.

func (*LinearSegmentedCmap) Category

func (c *LinearSegmentedCmap) Category() Category

func (*LinearSegmentedCmap) N

func (c *LinearSegmentedCmap) N() int

func (*LinearSegmentedCmap) Name

func (c *LinearSegmentedCmap) Name() string

func (*LinearSegmentedCmap) Resampled

func (c *LinearSegmentedCmap) Resampled(n int) Cmap

func (*LinearSegmentedCmap) Reversed

func (c *LinearSegmentedCmap) Reversed() Cmap

func (*LinearSegmentedCmap) WithExtremes

func (c *LinearSegmentedCmap) WithExtremes(under, over, bad *gg.RGBA) Cmap

type ListedCmap

type ListedCmap struct {
	// contains filtered or unexported fields
}

ListedCmap is a discrete colormap defined by an explicit color list. It is the backing type for qualitative palettes (tab10, Set1, etc.) and also for resampled continuous cmaps.

func NewListed

func NewListed(name string, cat Category, colors []gg.RGBA) *ListedCmap

NewListed constructs a discrete colormap from a slice of colors. The slice is copied; the caller may mutate the input afterwards safely.

func (*ListedCmap) At

func (c *ListedCmap) At(t float64) gg.RGBA

At returns the i-th color where i = floor(t * N). t in [0,1] maps to indices 0..N-1.

func (*ListedCmap) Category

func (c *ListedCmap) Category() Category

func (*ListedCmap) Color

func (c *ListedCmap) Color(i int) gg.RGBA

Color returns the i-th color directly, cycling i modulo N. Use this when applying a qualitative palette to discrete categories.

func (*ListedCmap) Colors

func (c *ListedCmap) Colors() []gg.RGBA

Colors returns a copy of the color list.

func (*ListedCmap) N

func (c *ListedCmap) N() int

func (*ListedCmap) Name

func (c *ListedCmap) Name() string

func (*ListedCmap) Resampled

func (c *ListedCmap) Resampled(n int) Cmap

func (*ListedCmap) Reversed

func (c *ListedCmap) Reversed() Cmap

func (*ListedCmap) WithExtremes

func (c *ListedCmap) WithExtremes(under, over, bad *gg.RGBA) Cmap

type LogNorm

type LogNorm struct {
	Vmin, Vmax float64
	// contains filtered or unexported fields
}

LogNorm performs base-10 log scaling between Vmin and Vmax. Vmin must be strictly positive after training; values v <= 0 yield NaN.

func (*LogNorm) Bounds

func (n *LogNorm) Bounds() (float64, float64)

func (*LogNorm) Inverse

func (n *LogNorm) Inverse(t float64) float64

func (*LogNorm) Norm

func (n *LogNorm) Norm(v float64) float64

func (*LogNorm) Train

func (n *LogNorm) Train(col dataset.AnyColumn) error

type Norm

type Norm interface {
	// Norm transforms v -> [0,1]. NaN is returned as NaN.
	Norm(v float64) float64

	// Inverse maps t in [0,1] back to data space.
	Inverse(t float64) float64

	// Bounds returns the current trained data range.
	Bounds() (vmin, vmax float64)

	// Train expands the bounds to cover values in col. Successive Train
	// calls accumulate (data range only grows).
	Train(col dataset.AnyColumn) error
}

Norm transforms an arbitrary scalar v into the unit interval [0,1] for input to a Cmap. Out-of-range values may be returned outside [0,1] — the consuming Cmap will clamp them or substitute Under/Over via [Cmap.WithExtremes].

type PowerNorm

type PowerNorm struct {
	Gamma      float64
	Vmin, Vmax float64
	// contains filtered or unexported fields
}

PowerNorm scales v with a power-law gamma between Vmin and Vmax. Equivalent to matplotlib's PowerNorm. Useful for emphasizing small or large values.

func (*PowerNorm) Bounds

func (n *PowerNorm) Bounds() (float64, float64)

func (*PowerNorm) Inverse

func (n *PowerNorm) Inverse(t float64) float64

func (*PowerNorm) Norm

func (n *PowerNorm) Norm(v float64) float64

func (*PowerNorm) Train

func (n *PowerNorm) Train(col dataset.AnyColumn) error

type Scale

type Scale struct {
	// contains filtered or unexported fields
}

Scale composes a Norm and a Cmap into a dataset-aware color mapper. It is the primary user-facing type produced by NewContinuous, NewDiscrete, and NewManual — and the value attached to a Plot via .ScaleColor / .ScaleFill / .ScaleColorManual.

Scale supports three usage modes:

  • Continuous: a Norm transforms numeric values into [0,1]; the Cmap samples a color at that t.
  • Discrete: string category labels are encoded into the index space of a ListedCmap. Cycling reuses colors when categories outnumber palette entries.
  • Manual: specific labels are pinned to specific gg.RGBA values via Scale.SetOverride. Overrides take precedence over both modes above in Scale.At.

func NewContinuous

func NewContinuous(c Cmap, n Norm) *Scale

NewContinuous returns a Scale that maps numeric data through n into the unit interval, then samples c at the resulting t. If n is nil, a default LinearNorm is created.

func NewDiscrete

func NewDiscrete(c Cmap) *Scale

NewDiscrete returns a Scale that maps category labels through c. Labels are encoded by their first-seen position; positions modulo c.N() select a color from c. Use Scale.SetCycle to control whether the palette cycles (default: cycles).

func NewManual

func NewManual(m map[string]gg.RGBA) *Scale

NewManual returns a Scale where every category label has an explicit color. Labels not in m fall back to a default Tab10 palette in the order they are trained.

func (*Scale) At

func (s *Scale) At(v any) gg.RGBA

At maps a value to a color. Accepts string, float64, int64, int, bool, or nil. The dispatch is:

  • if v is a string and an override exists, return the override;
  • else if Discrete, encode as a label (registering it on first sight) and look up via the underlying ListedCmap or falling back to cmap.At(idx/N);
  • else (continuous), pass v through Norm and sample Cmap.At.

NaN inputs sample the colormap's Bad slot.

func (*Scale) Categories

func (s *Scale) Categories() []string

Categories returns the list of trained category labels in encounter order. Empty for continuous scales.

func (*Scale) Cmap

func (s *Scale) Cmap() Cmap

Cmap returns the underlying colormap.

func (*Scale) Discrete

func (s *Scale) Discrete() bool

Discrete reports whether this Scale operates on category labels.

func (*Scale) Norm

func (s *Scale) Norm() Norm

Norm returns the underlying Norm. Returns nil for purely discrete scales that were never given one.

func (*Scale) SetCmap

func (s *Scale) SetCmap(c Cmap)

SetCmap replaces the underlying colormap.

func (*Scale) SetCycle

func (s *Scale) SetCycle(cycle bool)

SetCycle controls whether discrete category index values wrap modulo the palette size. When false, indices beyond the palette return the last color.

func (*Scale) SetNorm

func (s *Scale) SetNorm(n Norm)

SetNorm replaces the underlying Norm. Only meaningful for continuous scales.

func (*Scale) SetOverride

func (s *Scale) SetOverride(label string, c gg.RGBA)

SetOverride pins label to a specific color, overriding any computed value. Overrides apply in both continuous and discrete modes.

func (*Scale) Train

func (s *Scale) Train(col dataset.AnyColumn) error

Train adapts the Scale to the given column. For continuous Scales this expands the Norm bounds; for discrete Scales it appends new category labels to the encoding table. Calling Train multiple times accumulates.

type TwoSlopeNorm

type TwoSlopeNorm struct {
	Vcenter    float64
	Vmin, Vmax float64
	// contains filtered or unexported fields
}

TwoSlopeNorm normalises v asymmetrically around Vcenter — values below the center fill [0, 0.5] and values above fill [0.5, 1]. Standard choice for diverging colormaps where zero (or another anchor) should sit on the neutral midpoint regardless of how lopsided the data is.

func (*TwoSlopeNorm) Bounds

func (n *TwoSlopeNorm) Bounds() (float64, float64)

func (*TwoSlopeNorm) Inverse

func (n *TwoSlopeNorm) Inverse(t float64) float64

func (*TwoSlopeNorm) Norm

func (n *TwoSlopeNorm) Norm(v float64) float64

func (*TwoSlopeNorm) Train

func (n *TwoSlopeNorm) Train(col dataset.AnyColumn) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL