Cells Dividing: 3D Cellular Biology Simulation with Genealogical Lineage Tracking
#worksona#simulation#three-js#biology#webgl#visualization
David OlssonCells Dividing is a browser-native 3D simulation of cellular division and colony growth. Three.js and WebGL render cells as spheres in a three-dimensional space. Each cell divides, drifts according to configurable physics parameters, and eventually dies. The simulation starts from a single seed cell and produces an expanding colony whose structure depends entirely on the parameter configuration the user sets before starting.
The genealogical lineage tracker is the defining feature. Every time a cell divides, the application writes a record to IndexedDB capturing the new cell's identifier, its parent's identifier, its generation number, its position at birth, and a null diedAt field that gets populated when the cell is marked dead. The result is a complete family tree stored as a flat table of parent-child relationships โ a directed acyclic graph that can be reconstructed from the export at any depth.
Chart.js analytics panels show population growth curves, generation distribution histograms, and event frequency charts. An optional LLM chat panel accepts natural language questions about the current simulation state and queries the IndexedDB data to answer them.
Why is it useful?
Cellular biology instruction typically runs into one of two constraints. Lab work requires physical equipment, reagents, and significant setup time. Heavy scientific software requires installation, licensing, and domain expertise to operate. Both constraints make it difficult to use cellular division as a teaching tool outside of a fully equipped lab context.
A browser simulation removes both barriers. Cells Dividing runs on any device with a modern browser. There is nothing to install. A student can observe mitosis, adjust the division rate, watch the population curve change, and export the lineage tree in an afternoon without specialized equipment.
The lineage tracking addresses a gap that most cell simulations leave open. Visualizations that show current state โ a field of spheres expanding across the screen โ are effective for demonstrating that cells divide. They do not answer questions about ancestry: which cells are clonal descendants of the same progenitor, how many generations separate two living cells, which lineages died out and when. Cells Dividing stores the complete family tree, so those questions are answerable after the fact by querying the IndexedDB data or the JSON export.
The LLM chat panel makes that queryable data accessible to students who do not want to write queries. A student can ask "which generation has the most living cells right now" or "how many cells have died in the last 30 seconds" and get a direct answer generated from the live database state.
How and where does it apply?
Educational demonstrations are the primary application: mitosis mechanics, population doubling time, clone selection, and the effect of varying division probability on colony morphology. The simulation parameters are exposed in a configuration panel so an instructor can prepare specific scenarios โ for instance, a high-mortality configuration that demonstrates selection pressure โ and share them as URL parameters or JSON files.
The lineage JSON export is a directed acyclic graph. Each node is a cell record and each edge is a parent-child relationship expressed by the parentId field. Any graph library โ D3.js, Cytoscape, NetworkX โ can ingest this structure directly for visualization or analysis. Researchers working on clonal expansion models can use the export as ground-truth synthetic data for testing graph algorithms.
Each cell record written to IndexedDB follows this shape. The parentId is null only for the founding seed cell. The generation field is derived by incrementing the parent's generation, so it is always consistent even when cells are written out of order during high-frequency division bursts.
const cellRecord = {
id: crypto.randomUUID(),
parentId: parent?.id ?? null,
generation: parent ? parent.generation + 1 : 0,
bornAt: Date.now(),
position: { x, y, z },
diedAt: null
};
await db.cells.add(cellRecord);
The position field records the three-dimensional coordinates at the moment of birth. Over a full simulation run, the position data documents the spatial expansion of the colony and the physical relationship between lineages โ clonal clusters tend to remain spatially proximate because daughter cells are placed near their parents at division. That spatial structure is visible in the Three.js rendering and recoverable from the export.