Inspiration
As a pharmacy student, I kept noticing that a risk score is only useful if a clinician can see where the risk is and why. A single "CAD: yes/no" doesn't say which artery is in trouble. I wanted a tool that answers both questions at a glance: a 3D heart whose coronary arteries change colour with predicted risk, next to a plain-language explanation.
What it does
Enter a patient's demographics, history, exam, ECG, echo and lab values. The system predicts overall CAD status and 50% stenosis in the LAD, LCX and RCA, then colours each artery on an interactive 3D heart. Rotate, zoom and click a vessel to see its probability, a SHAP breakdown of the factors pushing it up or down, and the patient's measurements against typical ranges. A visible disclaimer states it is decision support and educational only. An assistant called Heartly answers questions about each result.
How we built it
Data. The Z-Alizadeh Sani extension dataset (303 patients, 55 features after encoding). LAD, LCX, RCA and Cath were removed from the inputs to prevent target leakage, and data-quality issues found in an audit were fixed.
Models. Logistic regression, random forest and gradient boosting were compared with $5 \times 5$ repeated stratified cross-validation. Preprocessing (imputation, scaling) is fitted inside each fold, so test patients never influence it. Models were chosen by mean ROC-AUC, then calibrated with Platt scaling:
$$p_{\text{cal}} = \sigma\big(a \cdot \operatorname{logit}(p) + b\big)$$
Each target got its own cutoff, chosen to maximise Youden's index:
$$J = \text{sensitivity} + \text{specificity} - 1$$
Honest cross-validated AUC:
- CAD: 0.930 (random forest)
- LAD: 0.843 (random forest)
- LCX: 0.727 (random forest)
- RCA: 0.718 (logistic regression)
Backend. A FastAPI service with /features and /predict endpoints returns calibrated probabilities, per-vessel status and SHAP contributions.
Frontend. React, Vite and React Three Fiber. Each artery is a separately named mesh in the heart model (anatomy from BodyParts3D, CC BY-SA 2.1 JP), so colour, selection and camera focus map directly onto model output. Heartly calls the Groq API from the browser.
Challenges we ran into
- Leakage and honesty. A label-shuffle control gave AUC near $0.5$, confirming no leakage. We report nested cross-validated metrics, not in-sample ones.
- Weak LCX and RCA models. With one small dataset, AUC is only about $0.72$. The interface says so, and a wider "borderline" band covers scores just under the cutoff.
- Missing inputs. Silently filling key fields with dataset defaults produced an imaginary, very sick patient ($99.8\%$ CAD), so key fields are now required. Skipped optional fields are flagged as estimated.
- Colour meaning. Each vessel has a different cutoff, so colour is scaled so amber always sits at that vessel's own cutoff, using a colour-blind-safe palette.
- Mapping the heart. BodyParts3D comes as hundreds of separate mesh pieces, so we wrote a builder script to group them into named LAD, LCX and RCA parts.
Accomplishments that we're proud of
- Cross-validated AUC of $0.930$ for overall CAD, confirmed leakage-free by a label-shuffle control.
- Vessel-level predictions mapped one-to-one onto named 3D arteries, each coloured against its own cutoff.
- Honest reporting: nested cross-validation, calibrated probabilities, and weak LCX and RCA models flagged rather than hidden.
- A full pipeline from patient form to explained 3D result, with a pinned disclaimer and clear marking of estimated inputs.
What we learned
- Accuracy misleads on imbalanced targets (a do-nothing baseline scores $0.715$ on CAD), while AUC and Brier score stayed stable.
- Threshold-based metrics for weak models shifted noticeably between library versions, so we pinned scikit-learn 1.8.0.
- SHAP shows associations in this dataset, not causes. For example, dyspnea lowers RCA risk here, which we flag rather than explain away.
What's next for Heartly
External validation on another centre's data, clinician review of the reference ranges and tooltips, patient-specific anatomy in place of the illustrative heart, and a server-side assistant so no API key sits in the browser.
Log in or sign up for Devpost to join the conversation.