Spiral waves, arrhythmia and defibrillation in a living sheet of heart muscle.
A sheet of ventricular muscle runs the Aliev-Panfilov excitable-medium model: each cell has a membrane voltage and a slow recovery variable, integrated in 0.05 time-unit substeps, dozens per frame. Diffusion follows a curving muscle fiber field through a precomputed eight-neighbor tensor stencil, so waves run faster along the fibers and painted scar is a true insulating boundary. A stimulus that lands on the refractory tail of a passing wave breaks it, and the free ends curl into self-sustaining spiral waves whose cores are tracked as phase singularities. The ECG below is synthesized from the field itself as the dipole sum of the voltage gradient against two virtual electrodes, so it shows clean beats in sinus rhythm and a fast sine wave once spirals take over, until the defibrillator excites every cell at once and leaves the spirals nowhere to go.
Try it. Click or drag to stimulate the tissue (try just behind a passing wave), or pick Scar and Heal to paint and remove scar. Defib (or D, or a tap on the monitor) shocks the heart back to sinus rhythm, Pace (P) toggles the pacemaker, keys 1 to 3 pick tools, C clears scar and R starts over. Left alone, an autopilot delivers premature beats and shocks on its own.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a simulation of heart muscle with spiral waves using JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a full-window canvas that stays sharp on high-DPI screens. Simulate on a grid of about 200 by 120 cells in Float32Arrays, drawn through ImageData into an offscreen canvas and scaled up.
- Use the Aliev-Panfilov model. Each cell has a voltage u and a recovery variable v. Each step: du = D * laplacian(u) - k*u*(u - a)*(u - 1) - u*v and dv = (0.002 + 0.2*v / (u + 0.3)) * (-v - k*u*(u - a - 1)), with k = 8, a = 0.12, D = 1. Take 20 to 40 small Euler steps (dt = 0.05) per frame, double-buffering u.
- Every 60 time units, add a current to du in a small disc near the top left for 2 time units: a pacemaker.
- Color cells dark red at rest, bright orange where u is high and faint violet where v is high (the refractory tail).
- Clicking stimulates a disc at the pointer. Clicking just behind a passing wave should break it into a self-sustaining spiral.
Once that works, make it beautiful:
- Brighten cells where u rose since the last frame to make a glowing front, and add a cheap bloom from a downscaled copy drawn back additively.
- Let the user paint scar tissue that blocks conduction, and add a Defibrillate key that sets u to 1 in every living cell, which wipes out the spirals.
- Draw an ECG strip below: each sample, sum grad(u) dotted with grad(1/r) from two virtual electrodes, and plot it like a hospital monitor.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as fiber anisotropy that makes waves travel faster in one direction, tracking the spiral tips as phase singularities, or reducing the recovery rate until spirals break up into fibrillation.