IcebergSim RCT

A clinical trial simulator — experience signal, noise, and sample size first-hand. Simulate thousands of randomized controlled trials and watch how your assumptions shape power, Type I error, and validity.

spec 2.0.0-alpha.1 236 engine tests Python · numpy · FastAPI · React MIT license
View on GitHub Run it locally
Scatter of relative risk versus p-value, one point per simulated trial, with the alpha = 0.05 significance line
600 simulated trials of one design (400 patients, 20% vs 10% event risk, seed 101) — every dot is a whole trial. This figure was generated by the engine itself.

What it does

Quick two-arm trials

Event risks, allocation, α, and simulation count → power, ARR/RR/RRR/NNT with confidence intervals, and per-replicate plots.

“What if the trial goes badly?”

Loss to follow-up (with risk multipliers), noncompliance, crossover, and imperfect ascertainment — compare the pragmatic trial to the ideal one, side by side.

Sample size & power

Formula sample sizes for two proportions, then simulated power curves around them — under ideal and pragmatic assumptions.

Interim stopping rules

Peto, Pocock, and O'Brien–Fleming legacy threshold tables plus custom plans; see where trials stop and what it costs in Type I error.

Risk subgroups

Full trial scenarios per subgroup, aggregated by summing 2×2 counts per replicate — never by averaging effects — with a forest display.

Cluster designs

Post-only cluster trials (beta-binomial, ICC, design effects, three labeled analyses) and pre/post designs with correlated baselines.

The Phoenix principle

Code is ephemeral; specification is source; tests are truth.

IcebergSim RCT is regenerated from an implementation-independent specification (spec/) distilled from the historical ICEBERGSIM — the Controlled Trial Simulator created by Eduardo Bergel with David Sackett and an international consortium. Every behavior is pinned by language-agnostic canonical tests (spec/tests.yaml: all 19 cases and 5 property tests pass), and every result carries a reproducibility manifest: input hash, seed, RNG algorithm, spec version, and analysis method. Delete the implementation, regenerate it from the spec, and the tests must pass again.

Quick start

git clone https://github.com/ebergel/icebergsim-rct && cd icebergsim-rct
uv sync                            # Python engine + API deps
cd web && npm install && npm run build && cd ..   # build the UI once
uv run icebergsim-server           # → http://127.0.0.1:8000 (local-only)
# or use the engine directly from Python
from icebergsim import validate_trial_definition, simulate_trial
from icebergsim.io import load_definition

trial = validate_trial_definition(load_definition("spec/examples/simple_two_arm.yaml"))
result = simulate_trial(trial, include_type_i_error=True)
print(result.summary.power)        # 0.81…, reproducible from the seed

Design commitments

Pure statistical engine

Frozen data, injected randomness, no formulas in the UI. The web interface renders exactly what the engine reports — nothing more.

Honest by construction

Undefined quantities are null with a diagnostic, inconsistent scenarios are rejected with structured errors, and anti-conservative analyses are labeled as such.

Reproducible always

Same definition + same seed → identical arrays. Seeded PCG64 with independent named streams for null copies, subgroups, and scenario families.