Research proof of concept: not a medical device, not medical advice. Built and trained on synthetic patients only, then checked on open, de-identified real CGM data. Alerts and what-if results are illustrative, never for diagnosis, treatment or dosing.
Inspiration
About 101 million adults in India live with diabetes (ICMR-INDIAB-17, 2023), yet care is decided from snapshots: an HbA1c every few months, a fasting value at a visit. CGMs and wearables now record glucose every few minutes, but no clinician can watch a whole panel's streams, and nobody can safely ask "what if this patient skips tonight's glimepiride?" before the patient tries it. Indian T2D has its own shape: the "thin-fat" phenotype, rice-and-roti plates, and fasting days taken with a sulfonylurea, a classic hypoglycaemia trap.
I wanted a model of this patient that stays in sync with them and can be questioned: a digital twin, not another risk score. Pratibimb (प्रतिबिम्ब) means "reflection". I built it in October 2026 for the Happiest Health Digital Twin Challenge on Unstop (which is why the video and repo mention it), missed that deadline and never submitted it there.
What it does
Pratibimb is a clinician console for a doctor following people with Type 2 diabetes who wear a CGM and a wrist wearable. It supports three jobs: triage who needs a call now, understand why, and counsel with advice tested on the patient's own twin. The live demo uses synthetic patients and needs no account: open the console, pick a flagged patient, press Go live, then open the What-If Lab.
- Cohort triage: every synced twin, ranked by calibrated risk, with a 24-hour sparkline and open alerts.
- Virtual patient: CGM against the twin's band and a 4-hour forecast cone, with meals, doses and sleep. Go live replays the recorded future.
- Why the twin is worried: calibrated chances of a high (>250 mg/dL) within 2 hours, a low (<70) within 1 hour and a low tonight, with plain-language drivers such as "time since sulfonylurea dose".
- What-If Lab: bajra roti instead of rice, a walk after dinner, a skipped dose or a short night. For synthetic patient P0029, skipping the next glimepiride dose raises the 5-hour peak from 174 to 197 mg/dL. The online demo runs precomputed scenarios; custom ones need the local API.
- Inside the twin, EHR sheet, model card: physiology, an HL7 FHIR R4 record with an ABHA-format ID, and the evaluation numbers.
How we built it
- Twin: an extended Bergman minimal model with drug effects (metformin, sulfonylureas, DPP-4 and SGLT2 inhibitors, basal insulin), personalised from routine labs such as the TyG index and HbA1c.
- Sync: a 64-member Ensemble Kalman Filter re-estimates the state and six personal parameters (insulin sensitivity, beta-cell response, liver output and more) with each 5-minute reading, then forecasts 4 hours ahead.
- Risk layer: about 100 strictly causal features, 33 from the twin, feed three calibrated LightGBM classifiers, explained with TreeSHAP. No LLM is involved.
- Data: a separate, richer "truth" simulator generated 240 synthetic patients over 28 days, with illness, unlogged snacks, missed doses and sensor artefacts, so the twin is never graded on its own assumptions. The engine serves a Next.js console through FastAPI or, on Vercel, a static export.
Challenges we ran into
- Keeping evaluation honest: models never see true glucose or subtype labels; scoring uses held-out patients only.
- Raw forecast intervals covered only 36–43 % for a nominal 80 %; I widened them using validation patients.
- Lows are rare: the 1-hour hypo alert's precision is only 0.079, so alert fatigue is a real risk.
Accomplishments that we're proud of
- On 36 held-out synthetic patients: AUROC 0.937 for highs within 2 hours (median lead 80 minutes), 0.986 for lows within 1 hour and 0.938 for lows tonight. The hybrid beat machine learning without twin features on every task.
- Testing the unchanged twin on real patients' open data, and publishing the result where it lost.
What we learned
The real-data check was humbling. On 90 open, de-identified CGM records (87 people), the twin beat linear extrapolation at every horizon and persistence at 2 hours, but lost to persistence at 30–60 minutes and to a data-driven LightGBM forecaster everywhere (30-minute RMSE 27.3 vs 14.06 mg/dL). Twin features added no measurable discrimination, and the synthetic-trained risk model transferred poorly (AUROC 0.79 for >250 mg/dL). My synthetic cohort had 2.5× the real rate of ≥180 mg/dL events. The real records come from China and the USA, not India, without insulin users. Synthetic scores only show the method works if the world resembles the simulator; on real data, the twin's value is context and what-if, not raw accuracy.
What's next for Pratibimb
Recalibrate the simulator to real event rates; blend the twin with a data-driven forecaster for short horizons; validate on de-identified Indian records; run a usability study with clinicians; add regional languages. No clinical claim before prospective validation.
Built with AI assistance, credits and data sources
- AI assistance: built with Claude (Anthropic) via Claude Code; every commit carries a Claude co-author line. The video uses a synthetic voiceover (edge-tts).
- Real data (validation only, not redistributed): CGMacros (PhysioNet, CC BY-NC-SA 4.0) and ShanghaiT2DM (figshare, CC BY 4.0), via GlycoTwin, my companion project, whose LightGBM is the benchmark above. Only aggregate metrics are published.
- Credits: food values from IFCT 2017 and the International GI Tables 2021; Open Runde font (OFL); Unsplash photos; citations in the README. Code: Apache-2.0.
Built With
- docker
- fastapi
- fhir
- lightgbm
- next.js
- numba
- numpy
- python
- react
- scikit-learn
- scipy
- tailwindcss
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.