Inspiration
This is a Hackathon project for "Multimodal AI Hackathon 2026".
Coronary artery disease happens when the arteries that feed the heart become narrowed. The standard way to confirm it is an angiogram, which is invasive and expensive. We wanted to see how far ordinary clinical information (age, symptoms, ECG, echo and blood tests) can go before anyone needs that test. We also wanted the answer to be explained and honest about its limits, because a risk number with no reasons attached is hard to trust.
What it does
CRVP takes one patient's clinical record and estimates four probabilities: overall coronary disease, and a narrowing of 50% or more in each of the three main arteries (LAD, LCX and RCA). The results appear on a 3D heart that you can rotate, zoom and click. Each artery is coloured by its risk.
For every number the app shows:
- Why: which inputs pushed it up or down.
- How steady: a likely range, plus a word for each reason ("consistent", "varies between refits" or "unstable") that says how steady it was when the model was refitted.
- How far to trust it: the weaker models (LCX and RCA) carry a visible "low confidence" badge.
A "Model & validation" panel shows the full results and how they were checked. The app also has six real example patients, so it still works if the prediction service is down.
How we built it
- Data: the Z-Alizadeh Sani dataset from UCI, with 303 patients. We turned it into 57 model inputs.
- Models: for each of the four targets we compared logistic regression, random forest and gradient boosting.
- Each was scored with 5-fold cross-validation repeated 5 times, which is 25 fits each.
- Probabilities are calibrated inside each fold.
- The winner is chosen by the one-standard-error rule, not the raw maximum. Random forest won every target.
- Explanations: SHAP gives each input's contribution. The contributions add up exactly to the model's score.
- Backend: FastAPI, running on a small AWS EC2 instance behind API Gateway.
- Frontend: React and three.js (through React Three Fiber), hosted on Vercel.
- Anatomy: BodyParts3D meshes. The heart's colours are baked offline so the page loads fast.
- Tests: 143 automated tests cover the leakage guard, feature encoding, the metrics and the API.
Challenges we ran into
- Leakage: overall disease and the three arteries are closely tied, so it is easy for the answer to leak into the inputs. We used a fixed list of allowed inputs and removed the four answers from every model's inputs. We also checked each input on its own: none scores above 0.80 alone.
- Weak results for two arteries: LCX and RCA only reach about 0.70 AUC, and they miss more than half of narrowed arteries at the 0.5 threshold. We chose to show that clearly instead of hiding it.
- Small data: 303 patients means the scores move a lot between folds. That is why we used repeated cross-validation, a likely range, and stability words.
- No location information: nothing in the data says where in the heart a problem is, so the app has to say this on screen at all times.
- A 3D heart that hid its own arteries: the opaque heart wall covered the vessels, and the first version loaded slowly. We lifted the arteries off the wall and moved the colour work offline.
- Deployment: the free Hugging Face route turned out to need a paid plan, and AWS CloudFront needed account verification. We ended up on EC2 plus API Gateway.
Accomplishments that we're proud of
- Cross-validated ROC-AUC of 0.922 for overall disease and 0.850 for the LAD, with the weaker LCX (0.720) and RCA (0.705) reported openly.
- The explanations are exact: a test checks that the contributions add up to the model's score.
- The honesty layer is always on screen, not hidden in a tooltip: the no-location caveat, the low-confidence badges, the in-sample warning and the disclaimer.
- It is live and works end to end. If the prediction service fails, it falls back to stored examples and says so. It never passes off a stored number as a live one.
- It is a solo project, with a full write-up and tests.
What we learned
- A good score is not proof of a good model. We trusted the leakage checks more than any single number.
- Agreement between algorithms is a weaker check than it looks, because a leaked column helps all of them.
- With small data, report the spread, not just the average.
- Telling users what a model cannot do makes it more useful, not less.
- Some published studies on this dataset report higher per-artery accuracy than ours. We have not reproduced them and don't know why, and we would rather say that than guess.
What's next for CRVP
- Test the models on patients from a different hospital. This is the biggest missing piece.
- Predict how severe a narrowing is, not just whether it is 50% or more.
- Add inputs that carry location information, such as imaging, so the per-artery results can mean more.
- Understand the gap with published accuracy figures by reproducing those studies and comparing how they were validated.
- Tighten the deployment: restrict the API to our own website and add a proper HTTPS setup.
- Work with clinicians to check whether the explanations are useful and clear in practice.
Built With
- amazon-api-gateway
- amazon-ec2
- amazon-web-services
- cardiology
- clinical-decision-support
- data-visualization
- explainable-ai
- fastapi
- healthcare
- heart-disease
- machine-learning
- medical-ai
- python
- random-forest
- react
- react-three-fiber
- scikit-learn
- shap
- three.js
- trustworthy-ai
- typescript
- vercel
- vite
- webgl


Log in or sign up for Devpost to join the conversation.