anadol_webgpu · dataParticleField
Data Particle Field (Refik Anadol — Machine Hallucinations / AI Data Sculptures)
Inspired by Refik Anadol Studio's AI Data Sculptures and 'data universe' portraits (e.g. Quantum Memories, Coral Dreams, Machine Hallucinations — NYC): particles are sampled from a synthesised dataset — here a 2D Gaussian Mixture Model with K anisotropic clusters — and rendered as a luminous cloud whose colour encodes each particle's cluster assignment. The particles drift gently outward from their cluster centres while a low-amplitude noise kick gives the field a 'breathing' quality; the canvas fades slowly so successive splats accumulate into a layered data universe portrait — the same composition logic Anadol uses to render layered GAN embeddings from millions of source images.
Original: https://refikanadol.com/works/coraldreams/
▶ 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
Sample N particle positions from a K-component 2D Gaussian Mixture: x_i ~ Σ_k π_k N(μ_k, Σ_k). Each step, velocity is updated by outward drift from μ_{c_i}, low-amplitude Gaussian kick, and damping (v *= 0.92); positions are integrated and wrapped on a torus. Each particle is additively splatted into a fading float canvas coloured by c_i ∈ {0..K-1}.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 600 | 200–1500 | Square canvas side length (px). |
num_particles | int | 6000 | 100–50000 | Number of particles sampled from the mixture. |
num_clusters | int | 7 | 1–32 | Number of Gaussian components K. |
palette_size | int | 7 | 1–8 | Palette entries (max 8 curated). |
noise_scale | float | 0.4 | 0–5 | Per-step Gaussian noise amplitude. |
outward_drift | float | 0.02 | 0–0.2 | Radial drift velocity from each particle's cluster centre. |
fade | float | 0.985 | 0.85–1 | Per-step canvas fade factor. |
Reference
First 60 lines of reference.py. Full source:
library_external/anadol_webgpu/dataParticleField/reference.py
"""dataParticleField — Refik Anadol inspired data-particle field.
Inspired by Refik Anadol Studio's body of "AI Data Sculptures" and
"AI Data Paintings" (e.g. *Quantum Memories*, *Machine Hallucinations
— NYC*, *Coral Dreams*): a large cloud of data points, each positioned
and coloured according to an underlying dataset, on top of a faint
"data universe" canvas.
Here we synthesise the dataset as a 2D Gaussian Mixture Model (GMM)
with K clusters, then sample N particles from the mixture. Each
particle carries (x, y, vx, vy, cluster_id, alpha); every step we
apply gentle outward drift from each cluster centre plus low-amplitude
noise so the field breathes, and we additively splat each particle
into a canvas coloured by its cluster (Anadol's "data pigments").
The result is a constellation of luminous blobs — a static "data
universe" portrait of the underlying mixture.
Reference:
- https://refikanadol.com/works/coraldreams/
("Machine Hallucinations — Coral Dreams", RAS, 2021)
- https://www.nvidia.com/en-us/research/ai-art-gallery/artists/refik-anadol/
"""
from __future__ import annotations
from typing import ClassVar
import numpy as np
# A palette inspired by Anadol's coral / cosmos pigments.
_PALETTE = np.array(
[
(255, 90, 110), # 0 — coral
(250, 150, 60), # 1 — amber
(255, 220, 90), # 2 — gold
( 90, 230, 200), # 3 — mint
( 60, 160, 255), # 4 — azure
(140, 100, 255), # 5 — violet
(240, 100, 220), # 6 — magenta
(255, 255, 255), # 7 — accent white
],
dtype=np.float32,
)
class DataParticleField:
"""Particles sampled from a 2D Gaussian Mixture Model.
Parameters
----------
dim : int
Square canvas side length (px).
num_particles : int
Number of particles N to sample from the mixture.
num_clusters : int
Number K of Gaussian components in the mixture.
palette_size : int
Number of palette entries to cycle through cluster colours
(``<= 8`` since the curated palette has 8 swatches).
noise_scale : float Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/anadol_webgpu/dataParticleField/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.
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.
Latent Walk (Refik Anadol — Unsupervised / Machine Hallucinations)
anadol_webgpu · latentWalk
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.
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.