The 3D version renders substrate and inhibitor as spheres orbiting one enzyme and picks a winner of a position-weighted race each frame. This 2D version instead simulates a population of 36 independent enzyme molecules, each one a genuine continuous-time Markov chain over three states — free (E), substrate-bound (ES) and inhibitor-bound (EI) — stepped with real first-order and second-order rate constants, not a spatial capture radius.
E --k_on,S·[S]--> ES --k_cat--> E + product (turnover)
ES --k_off,S--> E (unproductive release)
E --k_on,I·[I]--> EI --k_off,I--> E (inhibitor blocks, no reaction)
Km = (k_off,S + k_cat) / k_on,S Ki = k_off,I / k_on,I
Steady state: v = k_cat·[S] / ( Km·(1 + [I]/Ki) + [S] ) (Vmax = k_cat, normalised to 1)
IC50 = Ki·(1 + [S]/Km) (Cheng–Prusoff, competitive case)
Every dot below is one enzyme molecule; its colour is its actual current CTMC state, not a visual stand-in. The measured v/Vmax box is the ensemble's live turnover rate — literally counted product-release events divided by population size and elapsed time — which converges onto the analytic curve as the population averages out its own thermal noise, exactly like a real single-molecule kinetics assay would.
- [S], Km, Ki, [I] sliders — set the true rate constants (see equations); every enzyme's transition probabilities update live.
- Enzyme grid — grey = free, blue = substrate bound, red = inhibitor bound; a green burst marks a real turnover (product release) event, with the ejected product particle obeying simple 2D drag-and-fade motion.
- Dose-response curve — analytic v/Vmax vs log[I] at the current [S]; the marker follows the [I] slider and the dashed line marks IC₅₀. Compare it against the measured stat box to see the stochastic ensemble tracking the deterministic law.