anadol_webgpu · latentWalk
Latent Walk (Refik Anadol — Unsupervised / Machine Hallucinations)
Inspired by Refik Anadol Studio's Unsupervised — Machine Hallucinations — MoMA (2022): a chain of N points is sampled from a synthetic 64-dimensional latent space (a smoothed random walk) and projected to 2D via a fixed random matrix; the path is integrated step-by-step with spherical-linear interpolation between adjacent chain points, so the rendered trail visualises the path the 'latent space browser' would take through the embedding. Each slerp sample is coloured by chain timestamp (blue→magenta gradient), echoing the artist's statement that 'each data connection is driven by an edge-detection algorithm and colorized by the density of its previous and next latent coordinates.'
Original: https://refikanadol.com/works/unsupervised/
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
Latent chain L ∈ R^{N×D} is built as a smoothed random walk and rescaled to a hypersphere. A fixed random projector P ∈ R^{2×D} maps each row to 2D; the walker advances by spherical-linear interpolation slerp(L[i], L[i+1], t) with t advancing by 1/walk_steps per frame, then plots the projected point on a fading translucent canvas.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 600 | 200–1500 | Square canvas side length (px). |
chain_len | int | 1200 | 100–8000 | Number of latent chain points N. |
latent_dim | int | 64 | 8–512 | Latent dimensionality D (Real StyleGAN2 ADA: 1024). |
walk_steps | int | 60 | 1–400 | Cumsum smoothing passes on the chain. |
projection_seed | int | 20240414 | 0–2147483647 | Seed for the fixed 2xD random projection (determinism). |
point_color_mode | str | time | null–null | time|depth|spiral — how each slerp sample is coloured. |
Reference
First 60 lines of reference.py. Full source:
library_external/anadol_webgpu/latentWalk/reference.py
"""latentWalk — Refik Anadol inspired latent-space walk.
Inspired by Refik Anadol Studio's *Unsupervised — Machine Hallucinations —
MoMA* (2022), in which a StyleGAN2 ADA model trained on MoMA's archive
is "walked" through its 1024-dimensional latent space. The artist
describes the visualisation as a real-time 7D trajectory (x, y, z, r, g,
b, time) drawn from points in the latent embedding.
Here we collapse the idea to a tractable numpy analogue: a chain of N
points in a synthetic ``D=64`` dimensional space (a smoothed random
walk — the "latent walk"), projected to 2D via a fixed random matrix
``P : R^64 -> R^2``. Each frame we integrate a step along the chain
(``slerp`` interpolation between the current pair of latent points),
drop a coloured point at the projected location, and recolour the
trail by timestamp so the path itself encodes time.
Reference:
- https://refikanadol.com/works/unsupervised/
("Unsupervised — Machine Hallucinations — MoMA", RAS, 2022)
- https://en.wikipedia.org/wiki/Refik_Anadol
"""
from __future__ import annotations
from typing import ClassVar
import numpy as np
class LatentWalk:
"""A synthetic latent-space walk projected to 2D.
Parameters
----------
dim : int
Square canvas side length (px).
chain_len : int
Number N of latent points in the synthetic embedding chain.
latent_dim : int
Dimensionality of the synthetic latent space (default 64, in the
spirit of small GANs; Anadol's StyleGAN used 1024).
walk_steps : int
Number of cumsum smoothing steps used to build the latent chain
(controls curvature / smoothness of the projected path).
projection_seed : int
Seed for the fixed random projection ``P`` (so the same params
always project the same chain to the same path).
point_color_mode : str
``"time"`` colours each point by chain-index (``t/N`` along a
blue→magenta gradient); ``"depth"`` colours by the latent
walk step index (paler near idle, brighter when actively
integrating); ``"spiral"`` modulates hue by slerp angle.
"""
family: ClassVar[str] = "anadol_webgpu"
sketch: ClassVar[str] = "latentWalk"
def __init__(
self,
dim: int = 600,
chain_len: int = 1200, Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/anadol_webgpu/latentWalk/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from anadol · webgpu
2D FFT Texture Spectrum (WebGPU butterfly FFT)
anadol_webgpu · fft2dTexture
The WebGPU butterfly 2D FFT pattern: stage by stage, a @compute shader reads two texels per output (input[p] and twiddle-weighted input[q]) and writes the combined result; after log2(N) horizontal stages, transpose, and log2(N) vertical stages, the 2D FFT is complete.
Compute Particle System (WebGPU @compute pattern)
anadol_webgpu · computeParticleSystem
The canonical WebGPU 'compute-to-render' pattern: a @compute shader updates N particles in a storage buffer (one thread per particle, simple Verlet-style integration: v += gravity; v *= drag; p += v; bounce off walls; life++; respawn if life>max), and a render pass consumes the same buffer as vertex data to draw point sprites.
Data Particle Field (Refik Anadol — Machine Hallucinations / AI Data Sculptures)
anadol_webgpu · dataParticleField
Inspired by Refik Anadol Studio's AI Data Sculptures and 'data universe' portraits (e.g.
Dreamscape Field (Refik Anadol — Dreams / Nature Dreams)
anadol_webgpu · dreamscapeField
Inspired by Refik Anadol Studio's Dreams series (Nature Dreams, Urban Dreams, Space Dreams and the MoMA Fluid Dreams algorithm): a smooth low-frequency Perlin noise field drives slow global drift while a finer detail octave adds turbulent perturbation — Anadol's fluid solver aesthetic realised with cheap numpy.
Parallel Reduction (WebGPU workgroup-shared-memory tree reduction)
anadol_webgpu · parallelReduction
The classic WebGPU parallel-reduction pattern: load N values into workgroup-shared memory, workgroupBarrier(), tree-reduce by stride (shared[lid.x] = op(shared[lid.x], shared[lid.x + stride]); stride /= 2), workgroupBarrier(), and emit per-workgroup partials from thread 0.
Tile Blur (WebGPU separable Gaussian tile-shared-memory blur)
anadol_webgpu · tileBlur
The WebGPU separable Gaussian blur primitive: a workgroup of TILE×TILE threads loads a tile+halo of the source image into workgroup-shared memory, workgroupBarrier(), convolves each pixel with a 1D Gaussian along the row, writes to a ping-pong texture; then a second compute pass applies the column-direction Gaussian on the intermediate texture.