Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FindMyHeart — Cardiometabolic Companion

Personalised metabolic syndrome tracker: reads the medical record, connects to wearable trends, and gives clinically-contextualised, medication-aware feedback on whether interventions are actually working.

Quick Start

# 1. Add your OpenAI key to .env
echo "OPENAI_API_KEY=sk-..." > .env

# 2. Start everything
./start.sh
# Opens http://localhost:5174

Manual start

# Backend (terminal 1)
conda activate local_llm
uvicorn backend.api.main:app --port 8001 --reload

# Frontend (terminal 2)
cd frontend && npm run dev

What it shows

  • Metabolic Syndrome Score — ATP III criteria, 5/5 evaluated with live interactive sliders
  • Biomarker Status — colour-coded cards with personalized targets (medication-aware)
  • Clinical Insights — GPT-4.1-mini narrative: "is this treatment working?" per medication
  • Lab Trends — recharts line charts with reference target lines
  • Wearable Trends — 90-day simulated series (HR, HRV, steps, sleep)
  • Interactive Input Panel — live MetS score recalculation from user-adjusted waist + BP values

Demo patient

Male, 48 · Metabolic syndrome · Family history: premature CAD Medications: Atorvastatin 40mg (8 wks) · Metformin 1000mg (12 wks) Story: statin working (LDL 165→95), metformin working (HbA1c 6.3→5.9), HDL still low, hs-CRP improving.


Biomarker Engine — Mathematics

HOMA-IR (Insulin Resistance Index)

HOMA-IR = (fasting_glucose_mg/dL × fasting_insulin_μU/mL) / 405

Reference: Matthews et al., Diabetologia 1985. Implemented in backend/engine/biomarker.py → compute_homa_ir(). Auto-computed whenever both fasting glucose and insulin readings are present. Clinical threshold for insulin resistance: HOMA-IR ≥ 2.5.


ATP III Metabolic Syndrome Criteria (≥ 3 of 5 → MetS positive)

# Criterion Threshold Note
1 Fasting glucose ≥ 100 mg/dL Latest reading used
2 Triglycerides ≥ 150 mg/dL Latest reading used
3 HDL-C (male) < 40 mg/dL Sex-specific
3 HDL-C (female) < 50 mg/dL Sex-specific
4 Blood pressure ≥ 130/85 mmHg or on antihypertensive Medication flag counts
5 Waist circumference (male) ≥ 102 cm ATP III
5 Waist circumference (female) ≥ 88 cm ATP III

MetS positive when criteriaMet ≥ 3.

BP criterion is met if the patient is on any antihypertensive medication (ACE inhibitor, ARB, CCB, beta-blocker, thiazide) regardless of current reading — consistent with ATP III rules for treated hypertension.

Implemented in backend/engine/mets.py → evaluate_mets().


EWMA Trend Detection

Exponentially Weighted Moving Average applied to each biomarker's time series:

μ_t = α · x_t + (1 - α) · μ_{t-1}
Parameter Value When used
α = 0.40 More weight to recent values < 10 readings (sparse lab data)
α = 0.15 Smoother signal ≥ 10 readings (dense wearable data)

Slope is estimated by ordinary least-squares linear regression. Dates are converted to fractional months to make the slope interpretable as units-per-month:

month(d) = 12 × year + month + day/30

β̂ = Σ (xᵢ - x̄)(yᵢ - ȳ) / Σ (xᵢ - x̄)²

Direction thresholds:

Condition Direction
` β̂
β̂ < 0 (lower-is-better biomarker) improving
β̂ > 0 (lower-is-better biomarker) worsening
β̂ > 0 (higher-is-better: HDL, HRV, steps, sleep) improving
β̂ < 0 (higher-is-better) worsening

Implemented in backend/engine/trends.py → ewma_trend(), direction_for_display().


Personalized Medication-Aware Targets

Default population-level thresholds are overridden when the patient's medication and risk profile support a tighter evidence-based target:

Medication class Biomarker Personalized target Guideline
Statin + high CV risk ¹ LDL-C < 70 mg/dL ACC/AHA 2018
Statin (no high CV risk) LDL-C < 100 mg/dL ACC/AHA 2018
Metformin / SGLT2 / GLP-1 HbA1c < 7.0% ADA 2024
Any antihypertensive Systolic BP < 130 mmHg ACC/AHA 2017
Any antihypertensive Diastolic BP < 80 mmHg ACC/AHA 2017

¹ High CV risk = family history of premature CAD or metabolic syndrome diagnosis.

Borderline zone: values within 15% above the target maximum are flagged borderline rather than out_of_target to reflect clinical grey zones.

Implemented in backend/engine/biomarker.py → personalized_targets().


Medication Response Signals

For each medication with a tracked start date, the engine computes a before/after signal per biomarker:

1. baseline = earliest reading of the biomarker (any date)
2. current  = latest reading
3. Δ        = current − baseline
4. weeks_on = (today − medication.startedAt).days / 7

Interpretation rules
  Lower-is-better (LDL, TG, HbA1c, glucose, BP, HOMA-IR):
    Δ < 0       → improving
    Δ > +1      → worsening
    else        → stable

  Higher-is-better (HDL, HRV, steps, sleep_hours):
    Δ > 0       → improving
    Δ < −1      → worsening
    else        → stable

Implemented in backend/engine/signals.py → response_signals().


Architecture

frontend/   React 19 + Vite + TypeScript + Tailwind v4 + recharts
backend/    FastAPI (local_llm conda env) + OpenAI GPT-4.1-mini
            ├── engine/
            │   ├── mets.py       ATP III scoring
            │   ├── biomarker.py  Status evaluation + personalized targets
            │   ├── trends.py     EWMA + slope regression
            │   └── signals.py    Medication response signals
            ├── config/
            │   └── thresholds.py Clinical reference ranges
            └── data/
                └── seed.py       Demo patient data generator

API endpoints

Method Path Purpose
GET /health Liveness probe
GET /seed Full pre-computed demo patient data
POST /narrative GPT-4.1-mini narrative cards (cached)
POST /compute Live engine re-evaluation (interactive panel)

Required env vars

Variable Required Notes
OPENAI_API_KEY Yes For narrative generation

Hackathon demo — not a medical device. For informational purposes only. Always consult your care team.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages