Interactive Sandbox
See it work — not a slideshow
Hands-on demos that run real CuRE logic in your browser, on synthetic data. No login, no setup — start with the Cascade randomization engine below, the same code we validate for statistical equivalence against the randomizeR and carat reference implementations.
Build a randomization schedule
Pick an algorithm, configure the arms and stratification, and generate an allocation sequence on synthetic subjects. Change the seed to see reproducibility; change the algorithm to see how each one trades off balance, predictability, and covariate control.
Arms shuffled within fixed-size blocks — balance is guaranteed at every block boundary.
Same seed → identical schedule, every time. That reproducibility is what makes a randomization list auditable.
Arm balance · 48 subjects
The vertical marker on each bar is the target allocation.
Allocation sequence
Why this is more than a toy
The schedule above is produced by a vendored, byte-for-byte copy of CuRE Cascade's randomization core — including its R-compatible MT19937 PRNG. In the product, that engine is validated for statistical equivalence against the randomizeR and carat packages as oracles, and every draw is written to the platform's OMOP store inside a 21 CFR Part 11 audit envelope. Here it runs entirely client-side on synthetic subjects.
Characterize a cohort, live
Define inclusion criteria over a synthetic OMOP CDM slice and watch the characterization table recompute in your browser — demographics, condition and drug prevalence, and lab distributions, each compared against the background population. Filter to a condition and the enriched comorbidities and shifted labs fall out of the real aggregation, not a script.
Inclusion criteria over a synthetic OMOP CDM slice of 600 persons.
Condition prevalence
| Condition | Cohort vs. source | Cohort | Δ |
|---|---|---|---|
| Hypertensive disorder | 28.3% (170) | — | |
| Obesity | 26.2% (157) | — | |
| Hyperlipidemia | 21.7% (130) | — | |
| Osteoarthritis | 19.2% (115) | — | |
| Major depressive disorder | 13.2% (79) | — | |
| Type 2 diabetes mellitus | 12.5% (75) | — | |
| Atrial fibrillation | 9.5% (57) | — | |
| Chronic kidney disease | 9.0% (54) | — | |
| Asthma | 8.3% (50) | — |
Lab measurements
| Measurement | N | Mean (SD) | Median | Source mean |
|---|---|---|---|---|
| Hemoglobin A1c % | 545 | 5.6 (0.8) | 5.4 | 5.6 |
| Systolic blood pressure mmHg | 566 | 127 (13) | 125 | 127 |
| Body mass index kg/m² | 547 | 28.1 (5.4) | 27.9 | 28.1 |
| Total cholesterol mg/dL | 522 | 194 (35) | 193 | 194 |
| eGFR mL/min/1.73m² | 525 | 86 (13) | 88 | 86 |
Drug exposure
| Drug | Cohort vs. source | Cohort | Δ |
|---|---|---|---|
| Lisinopril | 21.2% (127) | — | |
| Atorvastatin | 14.7% (88) | — | |
| Sertraline | 9.3% (56) | — | |
| Metformin | 9.2% (55) | — | |
| Albuterol | 7.3% (44) | — |
Bars show the cohort rate; the vertical marker is the rate in the full synthetic source population, so an enriched feature reads as a bar overshooting its marker. Every figure is aggregated in your browser from 600 synthetic OMOP persons — change a criterion and watch it recompute.
Why this is more than a toy
This is the OHDSI cohort-characterization pattern — the same shape as FeatureExtraction — running on real OMOP standard concept IDs (SNOMED conditions, RxNorm drugs, LOINC labs). Every count, prevalence, and mean is aggregated client-side from a synthetic population of 600 persons; nothing here calls a backend. In the product, CuRE Calculate runs this characterization methodology over a governed OMOP store and emits submission-grade, validated outputs.
Find a safety signal, live
Pick a drug–event pair from a synthetic spontaneous-reporting database, drag the observed co-report count, and watch the disproportionality statistics — PRR, ROR (both with 95% confidence intervals), the chi-square, and DuMouchel's Empirical-Bayes EBGM / EB05 — recompute in your browser, then the pair's triage move between validated, watchlist, and dismissed.
A synthetic spontaneous-reporting database of 60,000 reports across 5 drugs and 7 events.
| Event + | Event − | |
|---|---|---|
| Drug + | a = 288 | b = 1,312 |
| Drug − | c = 1,512 | d = 56,888 |
Drag above the expected count to manufacture disproportionality — watch EB05 shrink low counts back toward the null.
EB05 ≥ 2.0 and ≥ 3 co-reports ⇒ validated. Product default is 2.
EBGM is the Empirical Bayes Geometric Mean of the reporting ratio under a two-component Gamma-Poisson (DuMouchel MGPS) posterior; EB05 is its conservative 5th-percentile lower bound — the score Canary triages on because it self-corrects for the small counts that inflate raw PRR/ROR.
All pairs · ranked by EB05
| Drug → Event | a | PRR | EB05 | Disposition |
|---|---|---|---|---|
| SSRI-Z → Serotonin syndrome | 121 | 18.15 | 10.99 | Validated signal |
| Statin-Y → Rhabdomyolysis | 138 | 14.87 | 9.48 | Validated signal |
| Biologic-V → Injection-site reaction | 105 | 11.59 | 8.39 | Validated signal |
| Anticoagulant-X → GI haemorrhage | 288 | 6.95 | 5.42 | Validated signal |
| NSAID-W → Acute kidney injury | 191 | 5.00 | 3.97 | Validated signal |
| NSAID-W → GI haemorrhage | 163 | 3.41 | 2.79 | Validated signal |
| SSRI-Z → Nausea | 229 | 1.42 | 1.24 | Watchlist |
| SSRI-Z → Headache | 182 | 1.31 | 1.13 | Watchlist |
| NSAID-W → Nausea | 238 | 1.21 | 1.07 | Watchlist |
| Statin-Y → Acute kidney injury | 49 | 1.32 | 0.97 | Dismissed |
| Anticoagulant-X → Acute kidney injury | 48 | 1.21 | 0.89 | Dismissed |
| Statin-Y → Serotonin syndrome | 12 | 1.21 | 0.62 | Dismissed |
Every statistic is computed in your browser from the synthetic 2×2 tables — no backend. Notice a high raw count is not enough: a common event like a background headache can post a big a yet stay dismissed once EB05 shrinks it against how often it is reported anyway. That shrinkage is what separates a real signal from reporting volume.
Why this is more than a toy
These are the FDA/EMA/WHO-UMC disproportionality formulas — Evans (2001) PRR, van Puijenbroek (2002) ROR, and DuMouchel's (1999) Multi-item Gamma-Poisson Shrinker — ported faithfully from CuRE's signal-detection methodology, including the product's default MGPS prior and the EB05 ≥ 2 triage rule. The key move a real PV engine makes, and this demo shows, is shrinkage: a common event with a big raw count stays dismissed once EB05 corrects for how often it is reported anyway. In the product, Canary runs this over an OMOP-native report store and routes validated signals into case management.
Gate a release on re-identification risk
Tune k-anonymity, l-diversity, t-closeness, and the generalization budget on a synthetic OMOP release, and watch the equivalence classes reform, the privacy↔utility tradeoff shift, and the export gate open or close — computed live in your browser by the same generalize-then-suppress fixed point the product runs.
A synthetic release of 140 records — quasi-identifiers age, zip, sex and a sensitive diagnosis.
Minimum equivalence-class size. Classes smaller than k are generalized or suppressed.
Distinct diagnoses required per class — guards against the homogeneity attack.
Max EMD between class and global sensitive distribution (numeric attributes).
How far age can bin (10→20→40…) and ZIP can truncate (5→3→*) before a class is suppressed instead.
Privacy ↔ utility tradeoff
Tighten k or l and privacy rises but utility falls as more records suppress; spend more generalization budget to recover utility by merging classes instead. That is the officer's whole job — and it is a real fixed-point computation here, not a mockup.
Equivalence classes · generalized [age | zip | sex]
| Generalized quasi-identifier | Size | ℓ | k | l | t | Disposition |
|---|---|---|---|---|---|---|
| 0-39 · 020 · * | 9 | 6 | ✗ | ✓ | ✓ | Suppressed · k |
| 80-119 · 021 · * | 8 | 3 | ✗ | ✓ | ✓ | Suppressed · k |
| 40-79 · 020 · * | 8 | 6 | ✗ | ✓ | ✓ | Suppressed · k |
| 0-39 · 024 · * | 7 | 5 | ✗ | ✓ | ✓ | Suppressed · k |
| 40-79 · 024 · * | 6 | 5 | ✗ | ✓ | ✓ | Suppressed · k |
| 80-119 · 020 · * | 4 | 2 | ✗ | ✓ | ✓ | Suppressed · k |
| 0-39 · 021 · * | 3 | 3 | ✗ | ✓ | ✓ | Suppressed · k |
| 80-119 · 024 · * | 1 | 1 | ✗ | ✗ | ✓ | Suppressed · k/l |
| 20-29 · 021 · * | 25 | 7 | ✓ | ✓ | ✓ | Released |
| 60-69 · 021 · * | 16 | 5 | ✓ | ✓ | ✓ | Released |
| 40-49 · 021 · * | 16 | 6 | ✓ | ✓ | ✓ | Released |
| 30-39 · 021 · * | 15 | 4 | ✓ | ✓ | ✓ | Released |
| 70-79 · 021 · * | 11 | 5 | ✓ | ✓ | ✓ | Released |
| 50-59 · 021 · * | 11 | 6 | ✓ | ✓ | ✓ | Released |
Each row is an equivalence class after generalization — note how age widens into decade bins, zip truncates to three digits, and sex redacts to *. k-anonymity, l-diversity (distinct diagnoses), and t-closeness are computed in your browser for every class; nothing calls a backend.
Why this is more than a toy
This is a faithful, dependency-free copy of CuRE's re-identification-risk methodology — the same equivalence-class formation, k-anonymity, distinct l-diversity, and 1-D Earth Mover's Distance t-closeness (Li, Li & Venkatasubramanian 2007), driven by the identical fixed-point generalize-then-suppress loop. In the product that methodology is owned by CuRE Calculate and rendered by Curtain for a privacy officer to gate a release against 45 CFR §164.514 Expert Determination; here it runs entirely client-side on synthetic records. Every k, ℓ, and t figure is recomputed in your browser — no backend.
Flag the outlier site, live
Run centralized statistical monitoring across a synthetic multi-site study. Each site's Key Risk Indicators are scored against their thresholds and summed into a risk score; move the outlier sensitivity and watch the flags move; expand a site to see its KRI breakdown — including the AE under-reporting signal that catches missed safety events.
A synthetic study across 8 sites — six Key Risk Indicators evaluated per site over their operational data.
A site is flagged when its risk score is a robust z-score (median / MAD) of at least this above its peers. Lower to widen the net; raise to surface only the extreme outliers.
- Screen failure · dropout · enrollment
- Query rate · protocol deviations
- AE under-reporting (sidecar method)
Sites · ranked by additive risk score
| Key risk indicator | Value | Threshold | Weight | Status |
|---|---|---|---|---|
| Screen failure rate | 42% | > 30% | 6 | breach +6 |
| Subject dropout rate | 32% | > 20% | 8 | breach +8 |
| Enrollment rate (actual/planned) | 56% | < 70% | 5 | breach +5 |
| Open query rate per subject | 3.09 | > 2 | 6 | breach +6 |
| Protocol deviation rate | 21% | > 10% | 7 | breach +7 |
| AE under-reporting signal· sidecar13 obs vs 24 expected AEs | 0.008 | < 0.05 | 10 | breach +10 |
Risk score is the sum of breached KRI weights (TransCelerate RBQM · ICH E6(R3) catalog).
Every KRI value, breach, risk score, and z-score is computed in your browser from the synthetic site data — no backend. The KRI codes, thresholds and weights are the seeded CuRE Caliber catalog (TransCelerate / ICH E6(R3)); the AE under-reporting signal is the exact Poisson lower-tail probability that a site's few reported AEs would occur if it truly reported at the study rate — the simaerep concept that, in the product, runs in the oracle-validated calculate-stats sidecar.
Why this is more than a toy
The KRI codes, default thresholds, and additive weights are the seeded CuRE Caliber catalog — recognized TransCelerate RBQM and ICH E6(R3) indicators. Per the platform's analytics-placement boundary (ADR-PLT-044), Caliber itself does only threshold-and-weight math; the oracle-validated statistical methods live in the CuRE Calculate sidecar. The headline AE under-reporting signal here is the exact Poisson lower-tail probability that a site would report so few adverse events if it truly reported at the study rate — a faithful, self-contained stand-in for the sidecar's simaerep method. Everything is computed client-side on synthetic sites; nothing calls a backend.
Map FHIR to OMOP, field by field
Pick or edit a FHIR Condition resource and watch Conduct's mapper produce the OMOP condition_occurrence row live — resolving the source code to an OMOP standard concept (following Maps to when the source is non-standard), applying the onset-date priority chain, and flagging domain-routing or unmapped codes.
A non-standard ICD-10-CM source code — the resolver follows "Maps to" to the SNOMED standard concept, so source_concept_id ≠ condition_concept_id.
| condition_concept_id | 201826 |
| condition_source_concept_id | 45542738 |
| condition_source_value | http://hl7.org/fhir/sid/icd-10-cm|E11.9 |
| condition_start_date | 2022-11-30 |
| condition_end_date | ∅ |
| condition_type_concept_id | 32817 |
| condition_status_concept_id | 32902 |
| condition_status_source_value | active |
This is Conduct's real Condition mapper running client-side: the onset-date priority chain (onsetDateTime → onsetPeriod.start → recordedDate), the clinicalStatus→concept map, the EHR type concept, and the concept resolver that follows OMOP Maps to so a non-standard source code lands on the right standard concept while its origin is preserved in source_concept_id. Edit the JSON above and the row remaps instantly — no backend.
Why this is more than a toy
This is Conduct's actual Condition mapper, ported dependency-free from the platform monorepo (apps/conduct/…/mapping-engine): the same FHIR-system→OMOP-vocabulary table, vocabulary-priority coding selection, concept resolver, and field-for-field condition_occurrence construction. In the product Conduct owns the canonical FHIR→OMOP mapping (Conduit → Conduct → omop, per ADR-PLT-026) and resolves concepts against the full OMOP vocabularies; here it runs against a hardcoded vocabulary slice, entirely in your browser. No backend.
Catch a bad value as it's entered
Enter values into a sample case report form and watch Capture's edit checks fire — an out-of-range lab or a physiologically implausible vital auto-raises a data query on the spot, with a 21 CFR Part 11 audit attribution. Fix the value and the query clears; break a cross-field rule and a new one appears.
Subject 1042 · edit a value and validation re-runs on the spot.
Hemoglobin value 10.2 g/dL is outside the reference range (12–17.5). Please verify the source.
Systolic BP value 166 mmHg is outside the reference range (90–140). Please verify the source.
Each query is raised by the same field-save validation core CuRE Capture runs — the out-of-range comparator, cross-field consistency checks, template rendering, and the active-query de-duplication guard, all computed in your browser. In the product each auto-query is written with a 21 CFR Part 11 audit trail (source AUTO, opened by the system user, timestamped and hash-chained) and routed to a coordinator; here nothing calls a backend.
Why this is more than a toy
The validation running here is Capture's actual field-save auto-query core, ported dependency-free from the monorepo (apps/capture/…/data-capture/auto-query-service.ts): the out-of-range comparator, cross-field consistency checks, the query-template renderer, and the active-query de-duplication guard, producing the same QueryFlag shape (source AUTO, status OPEN, system-attributed). In the product each query carries a hash-chained 21 CFR Part 11 audit trail and routes to a coordinator; here it all runs client-side on synthetic data. No backend.
A demo for every app
Each CuRE app has a workflow worth touching. We're building them out one at a time — live ones are reachable now; the rest are on the way. All synthetic, all in-browser.
Generate a real randomization schedule — block, stratified, biased-coin, or minimization — and watch arm balance hold.
Try itParse a free-text ISCN karyotype string into structured, queryable data in your browser.
Try itType into a sample eCRF and watch AI validation flag an out-of-range lab and auto-raise a query.
Try itPaste a CSV header row and see columns classified to OMOP domains with confidence scores.
Paste a FHIR Condition resource and watch it map to an OMOP condition_occurrence row.
Try itBuild a cohort over a synthetic OMOP slice and see the characterization table compute live.
Try itComplete an EQ-5D ePRO instrument and see the validated index score computed instantly.
Pick a synthetic patient and watch an OMOP cohort rule fire a point-of-care alert.
Step through study startup milestones and an enrollment funnel on a synthetic study.
Run centralized statistical monitoring across synthetic sites and flag the outlier.
Try itEnter drug–event counts and compute PRR / ROR / EB05 disproportionality signals.
Try itCompute k-anonymity / l-diversity on a synthetic release and gate it for export.
Try itSubmit a sample AI call and watch the hash-chained audit entry append — then verify the chain.
Drop a document title and see it classified to its DIA TMF zone with a readiness score.
Match a synthetic protocol's criteria against computed site-capability profiles.
Walk a deviation into a CAPA, with the linked training and evidence trail.
Assemble an eCTD sequence (new / replace / append / delete) and see the lifecycle tree.
Track a registration across health authorities through variations and renewals.
Diff two label versions and inspect the structured product (SPL) record.
Planned · cross-app
The whole platform, end to end
The point of CuRE is that the apps share one governed record. These guided journeys will let you follow a single synthetic case across app boundaries — the story no single-app demo can tell.
One governed record, every app
Follow one synthetic patient as their data lands, maps to OMOP, is captured, analyzed, surfaced at the point of care, and screened for safety signals.
Design once, generate everywhere
Change one study-design element and watch the CRF, SDTM mapping, and define.xml regenerate from the shared metadata repository.
RWD-to-submission evidence chain
Trace an adverse event from capture, to an E2B(R3) case, into the TMF, and out as an eCTD sequence — one sealed evidence chain.
Randomize, supply, analyze
A randomization and dispensation event written to the OMOP store is read straight back by analytics — no separate IRT silo.
Safety signal to quality action
A pharmacovigilance signal becomes a quality KRI, which opens a CAPA — the safety-and-quality loop on one substrate.
Want to run this on your own data?
The sandbox is synthetic. Let's talk about a walkthrough on a workflow that matches your program.