# palette

Python API: `luxonis_ml.utils.color.palette`

Distinct class colors from a pluggable, index-based generator.

A
[Palette](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md)
hands each new class the next color from a color generator: a callable `int -> Color` that maps a sequence position to a color.
The default generator,
[GoldenRatioColors](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md),
offsets each hue from the last by the golden angle (~137.5°) so no two classes land on a near-identical hue — the failure mode a
fixed palette (or a hash into one) can't avoid once the class count approaches the palette size. Class labels stay on this
distinct-hue scheme on purpose; the Luxonis brand colors are reserved for chrome (see
[luxonis_ml.utils.color.brand](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/brand.md)),
though
[SequenceColors](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md)
lets a caller anchor a palette to the brand
[BRAND_COLORS](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md)
when they want to.

Swapping the whole color scheme is a single argument — `Palette(generator=...)` — so the strategy lives in exactly one place and
callers only ever touch
[Palette.color_for](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md).

Because the spacing guarantee only holds for sequential indices, colors are assigned in order of first appearance and memoized:
within a process, a class keeps its color across every image (the module-level
[DEFAULT_PALETTE](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md)
is shared). The trade-off is that a class's color depends on the order classes are first seen, not on its name alone — stable
within a run and across runs that request classes in the same order, but not across arbitrary reorderings. Pin a color explicitly
with
[Palette.pin](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md)
or by pre-registering classes in a fixed order when a name must map to one exact color forever.

## Classes

### GoldenRatioColors

Maps a sequence index to a distinct color via golden-ratio hue spacing.

This is the default
[ColorGenerator](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md).
Every knob that shapes the look lives here, so restyling the whole palette means constructing one of these (or any other `int ->
Color` callable) and passing it to
[Palette](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md).

> **Examples**
> ```pycon
>>> gen = GoldenRatioColors()
>>> gen(0) == gen(0)
True
>>> gen(0) == gen(1)
False
```

#### Attributes

##### hue0

Hue of index 0, in `[0, 1]` turns (default a blue).

##### lightness

Base lightness of every color, in `[0, 1]`.

##### lightness_jitter

Peak lightness deviation from `lightness`, applied via a second low-discrepancy sequence so brightness varies subtly (which keeps colors apart even when hues get crowded at high class counts).

##### saturation

Fixed saturation of every color, in `[0, 1]`.

### Palette

Assigns colors to classes in order of first use, from a color generator.

> **Examples**
> A class keeps its color; different classes get different colors:

```pycon
>>> p = Palette()
>>> p.color_for("car") == p.color_for("car")
True
>>> p.color_for("car") == p.color_for("bus")
False
>>> len(p)
2
```

Two fresh palettes agree as long as classes are requested in the same order (`"car"` is index 0 in both) ...

```pycon
>>> Palette().color_for("car") == Palette().color_for("car")
True
```

... but the color follows first-seen order, not the name, so reordering changes it:

```pycon
>>> Palette(["a", "b"]).color_for("b") == Palette(
...     ["b", "a"]
... ).color_for("b")
False
```

#### Methods

##### init

```python
def __init__(classes: Iterable[str] | None = None, *, generator: ColorGenerator | None = None, colors: Mapping[str, ColorLike] |
None = None):
```

Create a palette, optionally pinning class order and exact colors.

Parameters

 * `classes` (`Iterable[str] | None`): Class names to register up front, in the order that fixes their colors. Any class not listed is assigned on first use.
 * `generator` (`ColorGenerator | None`): The `int -> Color` strategy; defaults to [GoldenRatioColors](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md).
 * `colors` (`Mapping[str, ColorLike] | None`): Explicit `{class_name: color}` pins. A pinned class always gets exactly that color and never consumes a generator slot, so pins do not shift the sequence colors of the other classes.

##### at

```python
def at(index: int) -> Color:
```

Return the color for sequence position `index` (without registering it).

Parameters

 * `index` (`int`): The zero-based position in the generator's sequence.

Returns

 * `Color`: The generated [Color](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/base.md).

##### color_for

```python
def color_for(key: str) -> Color:
```

Return the color assigned to `key`, assigning a new one if unseen.

The first time a key is seen it takes the next color in the sequence; every later call for that key returns the same color. Two threads racing to register different keys get different colors: only the assignment is locked, so the common case of an already-colored key stays lock-free.

Parameters

 * `key` (`str`): The label (or any string identity) to color.

Returns

 * `Color`: The assigned [Color](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/base.md).

##### pin

```python
def pin(key: str, color: ColorLike) -> Palette:
```

Pin `key` to exactly `color` and return `self` for chaining.

A pinned class always gets this color from [color_for](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md), overriding any generated one, and never consumes a generator slot.

Parameters

 * `key` (`str`): The class name (or string identity) to pin.
 * `color` (`ColorLike`): The exact color for `key` (any [ColorLike](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/base.md)).

Returns

 * `Palette`: This palette, to allow fluent chaining.

##### with_colors

```python
def with_colors(colors: Mapping[str, ColorLike]) -> Palette:
```

Return a copy of this palette with additional class-color pins.

The copy shares the generator and inherits already-assigned colors and pins; `colors` are merged on top. The original is not mutated, so a shared palette can be specialized per render without side effects.

Parameters

 * `colors` (`Mapping[str, ColorLike]`): Extra `{class_name: color}` pins to add.

Returns

 * `Palette`: A new [Palette](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md) with the merged pins.

### SequenceColors

Hand out a fixed list of colors first, then fall back to a generator.

Wraps a list of `anchors` (e.g. the Luxonis [BRAND_COLORS](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md)) so the first classes seen get those exact colors, in order. Once the anchors run out, index `n` continues through `overflow` (a [GoldenRatioColors](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md) generator by default, queried with an index that restarts at the first post-anchor class), so any number of classes still receive distinct colors.

> **Examples**
> ```pycon
>>> from luxonis_ml.utils.color import Color
>>> gen = SequenceColors((Color(255, 0, 0), Color(0, 255, 0)))
>>> gen(0)
Color(r=255, g=0, b=0, a=255)
>>> gen(1)
Color(r=0, g=255, b=0, a=255)
>>> gen(2) == gen(2)  # overflow is deterministic
True
```

#### Attributes

##### anchors

Colors handed out for indices `0 .. len(anchors) - 1`.

##### overflow

Generator used once the anchors are exhausted.

## Attributes

### BRAND_COLORS

The Luxonis brand color sequence, for use with
[SequenceColors](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md).

### ColorGenerator

A callable mapping a zero-based sequence index to a
[Color](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/base.md).

### DEFAULT_PALETTE

The process-wide default
[Palette](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md),
shared so a class keeps its color.

Uses the distinct-hue
[GoldenRatioColors](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-ml/luxonis-ml-api-reference/utils/color/palette.md)
generator: label colors are chosen to stay far apart, not to match the brand (which is reserved for chrome).
