PTI

Persistent Traversal Identity

PTI is a hierarchical symbolic color addressing system. Every 24-bit RGB color has an 8-digit octal address that encodes its position as a traversal path through the RGB cube. It is simultaneously machine-precise and more hierarchically interpretable than other color encodings.

The address

Each digit selects one of eight anchor colors (fixed colors like Cyan or Red) at a given level of detail. The eight anchors span both additive (R, G, B) and subtractive (C, M, Y) primary systems, plus Black and White.

Take RGB(74, 180, 163), a muted teal. In PTI, it's 34324251.

The first digit alone places the color immediately in the Cyan family. The first two digits, 34, identify the Cyan→Red trajectory — the two most significant bits of every channel, already 75% of each channel's range and enough to be recognizably teal. This is the compositional interpretability claim: meaning builds with every digit, before the address is ever fully decoded.

The eight anchors

The digits \(0\)–\(7\) map to the eight vertices of the RGB cube, the fixed vocabulary every address draws from. They span the additive primaries (R, G, B), the subtractive primaries (C, M, Y), and black and white. Each anchor's index is its selection tuple \((p, q, s)\) read as \(4p + 2q + s\).

Color \((p, q, s)\) RGB Hex Index
Black \((0,0,0)\) (0, 0, 0) #000000 0
Blue \((0,0,1)\) (0, 0, 255) #0000FF 1
Green \((0,1,0)\) (0, 255, 0) #00FF00 2
Cyan \((0,1,1)\) (0, 255, 255) #00FFFF 3
Red \((1,0,0)\) (255, 0, 0) #FF0000 4
Magenta \((1,0,1)\) (255, 0, 255) #FF00FF 5
Yellow \((1,1,0)\) (255, 255, 0) #FFFF00 6
White \((1,1,1)\) (255, 255, 255) #FFFFFF 7

Linear algebraic formulation

Every color is 24 bits: 8 for red, 8 for green, 8 for blue. Stack them as a \(3 \times 8\) grid \(\mathbf{B}\): rows are R, G, B; columns are bit positions, most significant first. The color and its address are two ways of reading that one grid. For the teal above, RGB(74, 180, 163):

\[ \mathbf{B} = \begin{bmatrix} 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 \\ 1 & 0 & 1 & 1 & 0 & 1 & 0 & 0 \\ 1 & 0 & 1 & 0 & 0 & 0 & 1 & 1 \end{bmatrix} \]

Two weight vectors do the reading: \(\mathbf{w} = (4, 2, 1)^\top = (2^2, 2^1, 2^0)^\top\) across the three channels, and \(\mathbf{d} = (2^7, 2^6, \ldots, 2^0)^\top\) across the eight bit positions. Read across the rows, weighting by \(\mathbf{d}\): each row returns its channel value, the RGB color, \(\mathbf{c} = \mathbf{B}\,\mathbf{d}\). Read down the columns, weighting by \(\mathbf{w}\): each column collapses to one octal digit, the address, \(\mathbf{a} = \mathbf{B}^\top \mathbf{w} =\) 34324251.

\[ \underbrace{\;\mathbf{c} = \mathbf{B}\,\mathbf{d}\;}_{\text{RGB}} \qquad\qquad \underbrace{\;\mathbf{a} = \mathbf{B}^{\top}\mathbf{w}\;}_{\text{PTI}} \]

Same grid, two directions, lossless and bijective: RGB and PTI are two views of one 24-bit object. PTI simply keeps the column reading: the traversal that octree quantization and Morton codes computed ephemerally but never persisted. PTI persists it — not a transient calculation, but a stable identifier for the color.

Worked out for the same teal, \(\mathbf{B}^\top\) is the grid transposed, so each row is one bit plane \((r_i, g_i, b_i)\):

\[ \mathbf{a} = \mathbf{B}^\top \mathbf{w} = \begin{bmatrix} 0 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 1 \\ 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \\ 1 & 0 & 1 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 4 \\ 2 \\ 1 \end{bmatrix} = \begin{bmatrix} 0(4)+1(2)+1(1) \\ 1(4)+0(2)+0(1) \\ 0(4)+1(2)+1(1) \\ 0(4)+1(2)+0(1) \\ 1(4)+0(2)+0(1) \\ 0(4)+1(2)+0(1) \\ 1(4)+0(2)+1(1) \\ 0(4)+0(2)+1(1) \end{bmatrix} = \begin{bmatrix} 3 \\ 4 \\ 3 \\ 2 \\ 4 \\ 2 \\ 5 \\ 1 \end{bmatrix} = \texttt{34324251} \]

Depth

Depth is resolution. Keep all eight digits for the exact color, or drop the tail for a coarser stand-in in the same family. Depth 4 is always within 16 units per channel of the original; for this particular color, even depth 2 stays that close.

Color Explorer

PTI's Color Explorer opens on a complete map of \(\mathcal{C}_{24}\), the full color space, at the family level: all 64 depth-2 families, one 8×8 grid, indexed by their leading two digits. Every color in \(\mathcal{C}_{24}\) belongs to exactly one cell — no sampling, no approximation, nothing left out. Rows share a dominant color direction; columns share a secondary direction. The main diagonal holds the 8 anchor colors; the anti-diagonal holds complement pairs. It's not a color wheel, and it's not a continuous picker like HSL — it's a structure you drill into: click a family, not slide a value.

Open the Color Explorer →

Native palettes

No known prior system resolves color palettes directly from RGB: no color wheel, no perceptual model. The harmonies are structural, not curated: native to the address itself. Every color but the eight anchors has them built in. The most complete form is a set of eight colors, discovered directly from the address by a simple, well-defined operation — trivial to describe, but one that quietly reshapes the bit pattern of every channel at once. Three such sets are shown below.

21054645 #1F8451
10546452 #3E09A2
05464521 #7C1245
54645210 #F8248A
46452105 #F14815
64521054 #E3902A
45210546 #C72154
52105464 #8F42A8
07316524 #4D6A74
73165240 #9AD4E8
31652407 #35A9D1
16524073 #6A53A3
65240731 #D4A647
52407316 #A94D8E
24073165 #539A1D
40731652 #A6353A
75130743 #C695F5
74375130 #D8B2BE
13074375 #1B56D7
07437513 #6C595F
37513074 #63CAFA
30743751 #36ACAF
43751307 #B1657D
51307437 #8D2BEB

Open the Rotation Orbit Explorer →

Use Cases

More interactive demonstrations of the addressing system, such as a conversion tool, depth-level exploration, family filtering, and catalog organizing.

Open Use Cases →

Resources

Full formal treatment (encoding algorithm, prefix semantics, gray property, complement property, CSS identity, and rotation-orbit structure) — including the derivations behind the palette harmonies above — has been submitted to arXiv; a direct link will be added once it's live.

A reference implementation (Python and JavaScript) is available on GitHub.

A Figma plugin is in the works.