Skip to content

Repository files navigation

CardioScan 🫀

AI-Powered Rheumatic Heart Disease Screening Prototype

🏆 1st Place — EWH × SUABE Designathon 2026, Fiji

tests

A low-cost digital stethoscope that screens for signs of Rheumatic Heart Disease using machine learning — designed for community health workers in remote Fiji.

⚠️ CardioScan is a research and education prototype, not a medical device. It is not a diagnosis. It is validated only on the PhysioNet dataset and is unvalidated on real device hardware, where accuracy can drop sharply (see Honest evaluation). Always consult a qualified clinician.


What is CardioScan?

Rheumatic Heart Disease (RHD) is largely preventable with a $0.50 penicillin injection — but only if caught early. In remote Fiji there are few cardiologists, little echocardiography, and no affordable screening tools.

CardioScan is a proof of concept that puts AI-assisted cardiac screening in the hands of community health workers for under $150:

  • ⏱ 15-second scan — plug in, place on chest, get a screening result
  • 🤖 Random Forest model trained on 3,240 PhysioNet clinical recordings
  • 🌐 Browser-based — runs in Chrome via the Web Serial API, no install needed
  • 🔌 Hardware + software — an Arduino captures heart sounds, Python + Flask extracts features and runs the model, which returns Clear / Refer / Inconclusive

Architecture

Browser (Chrome / Edge)
    │  Web Serial API (USB)  ──►  Arduino Nano + microphone (streams ADC samples)
    │  POST /api/analyse  { samples: [...] }
    ▼
Flask server (server.py)
    │  features.py   → 90-dim feature vector (resampled to 500 Hz)
    │  rhd_model.pkl → Random Forest → P(abnormal)
    │  decision.py   → Clear / Refer / Inconclusive  (data-driven thresholds)
    ▼
Website displays the verdict + probabilities

The feature pipeline lives in one shared module (features.py) imported by training, the server, and the CLI detector, so training and inference can never drift apart.


Honest evaluation

The model is strong within the PhysioNet distribution but does not generalize to unseen recording setups — the honest predictor for real hardware. Both numbers are printed by train_model.py, and the study is reproduced in experiments/.

Metric What it measures Result
Same-distribution (shuffled 5-fold) Train/test from the same sources ROC-AUC 0.951 ± 0.009
Held-out test accuracy 648 unseen PhysioNet recordings 92.75%
Cross-source (leave-one-source-out) A recording setup never seen in training ROC-AUC 0.569 ± 0.132

Feature engineering can't close that gap — band-pass, rhythm features, and augmentation all hit the same ~0.57 ceiling (see experiments/README.md). The real fix is collecting labeled audio from the actual device.

Screening-tuned decision

Instead of the naive 0.5 cutoff, the abnormal probability is turned into a three-way result using thresholds derived from out-of-fold reliability (train_model.py → model/thresholds.json, applied by decision.py):

P(abnormal) Verdict
< 0.35 Clear (confidently normal)
0.35 – 0.53 Inconclusive (model unreliable here — repeat / refer)
≥ 0.53 Refer (confidently abnormal)

This flags ~89% of abnormal recordings (refer or inconclusive) versus 71% at the default 0.5 cutoff — the right trade-off for a referral tool, where a missed case is far costlier than an extra referral. Inconclusive results still lead to follow-up, so nothing is falsely cleared.


Getting started

Prerequisites

  • Python 3.11–3.14
  • Chrome or Edge (for the Web Serial API), if using the hardware

1. Clone and install

git clone https://github.com/7tharva/CardioScan.git
cd CardioScan
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt      # Windows
# .venv/bin/pip install -r requirements.txt          # macOS/Linux

2. Run the server

.venv\Scripts\python server.py

Open http://localhost:5000. Plug in the Arduino and click Begin Scan, or use the built-in demo clips (no hardware needed):

  • Shift + N → a normal-heart demo
  • Shift + A → an abnormal/RHD demo

Use it from another device on your network

The server binds to 0.0.0.0, so from a phone or laptop on the same Wi-Fi open http://<this-PC-IP>:5000 (allow port 5000 through the firewall). The frontend calls whatever origin served the page, so LAN and tunnels work with no code edits.

(Optional) Retrain the model

Download PhysioNet/CinC 2016 from https://physionet.org/content/challenge-2016/1.0.0/, then point CARDIOSCAN_DATA_DIR at the folder containing training-a … training-f:

set CARDIOSCAN_DATA_DIR=path\to\training
.venv\Scripts\python train_model.py

This regenerates model/rhd_model.pkl and model/thresholds.json and prints the full evaluation.


Testing

Self-contained smoke tests (only need the repo — model + demo clips):

.venv\Scripts\pip install -r requirements-dev.txt
.venv\Scripts\python -m pytest -q

They check the feature length, model compatibility, the decision bands, and that the bundled demo clips still classify correctly. CI runs them on every push (.github/workflows/tests.yml).


Deploy (free, public)

Host the app on Hugging Face Spaces (Docker) for a public URL anyone can use — the bundled demo needs no dataset or hardware, and with an Arduino on the visitor's own laptop the live Web Serial scan works too (over HTTPS). A Dockerfile is included; see DEPLOY.md for step-by-step setup.


Project structure

CardioScan/
├── index.html            # Frontend (Web Serial capture, results UI)
├── server.py             # Flask backend (inference, demo endpoints)
├── features.py           # Shared 90-dim feature pipeline (used everywhere)
├── decision.py           # Clear / Refer / Inconclusive thresholding
├── train_model.py        # Training + evaluation + threshold derivation
├── detector.py           # Standalone CLI detector over serial
├── test.py               # Sanity-check predictions on dataset files
├── find_abnormal.py      # Rank dataset clips by confidence (demo picking)
├── demo_audio/           # Bundled PhysioNet clips for the no-hardware demo
├── experiments/          # Cross-source generalization study
├── tests/                # pytest smoke tests
├── RHD_Arduino/          # Arduino firmware (.ino)
├── model/
│   ├── rhd_model.pkl     # Trained Random Forest
│   └── thresholds.json   # Data-driven decision thresholds
├── Dockerfile            # Container for free hosting (see DEPLOY.md)
├── requirements.txt      # Runtime dependencies (pinned)
├── requirements-dev.txt  # + test dependencies
└── README.md

Hardware

Component Specification
Microcontroller Arduino Nano
Microphone Electret microphone module (pin A0)
Connection USB serial → Chrome Web Serial API

Known limitation (the biggest open issue): the firmware streams samples over serial at 9600 baud, where transmission time — not the intended delay — sets the real sample rate (~130 Hz, not the assumed 500 Hz). Combined with the electret front-end, the device does not yet capture the full cardiac frequency range, and its recordings are an unseen domain for the model. A higher baud rate + fixed-timer sampling, a MEMS acoustic sensor, and on-device data collection are the priorities for a field-ready version.


Roadmap

  1. Fix the hardware sampling — 115200 baud + fixed-timer capture so the device delivers a known, consistent rate.
  2. Collect local device data — partner with CWM Hospital, Suva; label real recordings and retrain on the target domain (the only reliable fix for the cross-source gap).
  3. MEMS microphone upgrade — capture the full cardiac frequency range.
  4. Standalone deployment — Raspberry Pi / STM32 with a lightweight model.
  5. Community pilot — deploy across remote island clinics in Fiji.

Tech stack

Layer Technology
Frontend HTML · CSS · Vanilla JS · Web Serial API
Backend Python · Flask · flask-cors
ML / audio scikit-learn · librosa · NumPy · SciPy
Hardware Arduino Nano · electret microphone

References

  • PhysioNet/CinC Challenge 2016 — https://physionet.org/content/challenge-2016/
  • Wyber et al. (2024), Rheumatic heart disease in the Pacific, The Lancet Regional Health
  • Watkins et al. (2017), Global burden of rheumatic heart disease, NEJM

Acknowledgements

Built at the EWH × SUABE Designathon 2026. Thanks to organisers Sakura Brennan and Ayan Towhid.

License

MIT — free to use, modify, and distribute with attribution. Not a medical device.

CardioScan · Team HeartStoppers · University of Sydney · 2026

About

AI-powered RHD screening device — 1st Place EWH X SUABE Designathon 2026

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages