Thumbnail.

E8 v1

Description

Just like Surfer Dude, this image was inspired by Garrett Lisi’s An Exceptionally Simple Theory of Everything. This one represents an E8 Petrie projection. The Python source was written with Chatgpt, and executed in Google Colab.

import numpy as np
import colorsys
import math
from itertools import product
from PIL import Image

# === Configuration ===
SIZE       = 4096
RADIUS     = 6     # dot radius in pixels
ALPHA_BG   = 128   # 50% opacity for background
ALPHA_FG   = 255   # fully opaque for lines & dots
TOTAL_PIXELS = SIZE * SIZE
TOTAL_COLORS = 2**24  # 16,777,216

# === 1) Generate the 240 E₈ roots in ℝ⁸ ===
roots = []

# A-type: ±e_i ± e_j
for i in range(8):
    for j in range(i+1, 8):
        v = np.zeros(8, dtype=float)
        v[i], v[j] =  1, -1
        roots.append(v.copy());    roots.append((-v).copy())
        v[i], v[j] =  1,  1
        roots.append(v.copy());    roots.append((-v).copy())

# B-type: (±½,…,±½) with product(signs) = +1
for signs in product([1, -1], repeat=8):
    if np.prod(signs) == 1:
        roots.append(np.array(signs, dtype=float) * 0.5)

roots = np.vstack(roots)  # shape (240,8)

# === 2) Project into 2D via PCA/SVD ===
roots_centered = roots - roots.mean(axis=0)
U, S, Vh = np.linalg.svd(roots_centered, full_matrices=False)
proj2d = roots_centered @ Vh.T[:, :2]  # (240,2)

# === 3) Scale & translate into pixel coordinates ===
marg = 0.05 * SIZE
scale = (SIZE/2 - marg) / np.max(np.linalg.norm(proj2d, axis=1))
coords_f = proj2d * scale + SIZE/2  # floats
coords = np.round(coords_f).astype(int)

# === 4) Find all edges (⟨α,β⟩ = 1) ===
gram = roots @ roots.T
i_u, j_u = np.where(np.triu(np.isclose(gram, 1.0), k=1))
edges = list(zip(i_u.tolist(), j_u.tolist()))

# === 5) Bresenham line algorithm ===
def bresenham(x0, y0, x1, y1):
    dx = abs(x1 - x0); sx = 1 if x0 < x1 else -1
    dy = abs(y1 - y0); sy = 1 if y0 < y1 else -1
    err = dx - dy
    pixels = []
    while True:
        pixels.append((x0, y0))
        if x0 == x1 and y0 == y1:
            break
        e2 = 2 * err
        if e2 > -dy:
            err -= dy
            x0 += sx
        if e2 < dx:
            err += dx
            y0 += sy
    return pixels

# === 6) Generate circle mask offsets for dots ===
circle_offsets = []
for dy in range(-RADIUS, RADIUS + 1):
    dx_max = int(math.floor(math.sqrt(RADIUS*RADIUS - dy*dy)))
    for dx in range(-dx_max, dx_max + 1):
        circle_offsets.append((dx, dy))

# === 7) Collect pixel coordinates for lines & dots ===
used = np.zeros((SIZE, SIZE), dtype=bool)
line_pixels = []
for i, j in edges:
    x0, y0 = coords[i]; x1, y1 = coords[j]
    for (x, y) in bresenham(x0, y0, x1, y1):
        if not used[y, x]:
            line_pixels.append((x, y))
            used[y, x] = True

dot_pixels = []
for x0, y0 in coords:
    for dx, dy in circle_offsets:
        x, y = x0 + dx, y0 + dy
        if 0 <= x < SIZE and 0 <= y < SIZE and not used[y, x]:
            dot_pixels.append((x, y))
            used[y, x] = True

N_line = len(line_pixels)
N_dot  = len(dot_pixels)
N_bg   = TOTAL_PIXELS - N_line - N_dot

assert N_bg + N_line + N_dot == TOTAL_PIXELS, "Pixel count mismatch!"

# === 8) Build & sort full 24-bit palette by HSV (v, s descending) ===
# Create array of shape (16_777_216, 3)
palette = np.empty((TOTAL_COLORS, 3), dtype=np.uint8)
idxs = np.arange(TOTAL_COLORS, dtype=np.uint32)
palette[:, 0] = (idxs >> 16) & 0xFF
palette[:, 1] = (idxs >>  8) & 0xFF
palette[:, 2] = (idxs      ) & 0xFF

# Convert to HSV
# scaled to [0,1] floats
rgb_norm = palette.astype(float) / 255.0
hsv = np.array([colorsys.rgb_to_hsv(*c) for c in rgb_norm])
v = hsv[:, 2]
s = hsv[:, 1]

# Sort so brightest & most saturated first:
order = np.lexsort((-(s), -(v)))
sorted_palette = palette[order]

# === 9) Assign colors to lines, dots, and background ===
line_colors = sorted_palette[:N_line]
dot_colors  = sorted_palette[N_line:N_line+N_dot]
bg_colors   = sorted_palette[N_line+N_dot:]

# === 10) Create RGBA image and paint ===
img = Image.new("RGBA", (SIZE, SIZE))
pixels = img.load()

# Paint lines
for (x, y), (r, g, b) in zip(line_pixels, line_colors):
    pixels[x, y] = (int(r), int(g), int(b), ALPHA_FG)

# Paint dots
for (x, y), (r, g, b) in zip(dot_pixels, dot_colors):
    pixels[x, y] = (int(r), int(g), int(b), ALPHA_FG)

# Paint background
bg_iter = iter(bg_colors)
for y in range(SIZE):
    for x in range(SIZE):
        if not used[y, x]:
            r, g, b = next(bg_iter)
            pixels[x, y] = (int(r), int(g), int(b), ALPHA_BG)

# === 11) Save PNG ===
img.save("E8_Petrie_exact24bit_4096.png")
print("✅ Generated 4096×4096 E₈ Petrie projection using every 24-bit RGB color exactly once.")

Author

ACJ
53 entries

Stats

Date
Colors16,777,216
Pixels16,777,216
Dimensions4,096 × 4,096
Bytes8,107,597