Plan
For the prototype:
┌──────────────────────┐
│ FRONTEND │
│ │
│ Patient / Screening │
│ Upload / Results │
│ Reports / Dashboard │
└──────────┬───────────┘
│
HTTP
│
┌──────────▼───────────┐
│ BACKEND │
│ │
│ Auth │
│ Patients │
│ Screening Sessions │
│ Image Management │
│ ML orchestration │
│ Results │
│ Reports │
└──────┬───────┬───────┘
│ │
┌──────▼───┐ ┌─▼──────────┐
│ DATABASE │ │ FILE STORE │
│ │ │ │
│ Patients │ │ Fundus │
│ Sessions │ │ images │
│ Results │ │ Grad-CAM │
└──────────┘ │ reports │
└────────────┘
┌───────────────┐
│ ML ENGINE │
│ │
│ Quality │
│ DR grading │
│ Lesions │
│ Grad-CAM │
└───────────────┘
The critical architectural decision is:
The backend should not care how the ML model works.
Today the ML team may have a Python prototype. Later it may become MATLAB code, a MATLAB-generated service, or something else. The backend should simply send an image and receive a standardized result.
#2. Three things we're building now
#A. Backend
Responsible for:
- users
- patients
- screening sessions
- image uploads
- invoking ML
- storing predictions
- storing reports
- exposing APIs
- audit/history
#B. Frontend
Responsible for:
- login
- patient registration
- new screening
- image upload
- processing status
- results
- Grad-CAM visualization
- screening history
- report viewing
#C. Database/storage
Responsible for metadata, not necessarily the actual retinal images.
Database
│
├── users
├── patients
├── screening_sessions
├── images
├── predictions
├── lesions
└── reports
File/Object Storage
│
├── original images
├── processed images
├── Grad-CAM images
└── generated reports
#3. Suggested technology stack
#Frontend
React + TypeScript
React
TypeScript
Vite
#Backend
Python + FastAPI
FastAPI
│
├── REST API
├── authentication
├── image handling
├── ML orchestration
└── database access
#Database
PostgreSQL
#Image/file storage
For development:
/local storage
Later:
S3-compatible object storage
#ML
Keep this completely separate:
ML model
The backend talks to it through an interface.
#4. The database schema
Who operates the system.
users
-----
id
name
email
password_hash
role
created_at
Possible roles:
ADMIN
SCREENING_OPERATOR
OPHTHALMOLOGIST
The person being screened.
patients
--------
id
patient_code
name
age
sex
contact
created_at
One screening event.
screening_sessions
-------------------
id
patient_id
operator_id
status
created_at
completed_at
Possible statuses:
CREATED
IMAGE_UPLOADED
PROCESSING
COMPLETED
REVIEW_REQUIRED
FAILED
The actual image metadata.
images
------
id
session_id
original_path
processed_path
width
height
quality_status
created_at
Example:
quality_status:
PENDING
ACCEPTABLE
BORDERLINE
UNGRADABLE
#5. predictions
predictions
-----------
id
session_id
dr_grade
referable_dr
confidence
model_name
model_version
created_at
For example:
{
"dr_grade": 3,
"referable_dr": true,
"confidence": 0.91,
"model_name": "DRClassifier",
"model_version": "0.1.0"
}
#6. lesions
lesions
-------
id
session_id
type
confidence
x
y
width
height
severity
Possible:
MICROANEURYSM
EXUDATE
HEMORRHAGE
NEOVASCULARIZATION
#7. reports
reports
-------
id
session_id
report_path
generated_at
review_status
reviewer_id
reviewed_at
review_notes
ML
↓
Result
↓
Ophthalmologist
↓
Review
↓
Confirm / modify
↓
Final report
#8. API
#Patients
POST /api/patients
GET /api/patients
GET /api/patients/{id}
#Screening
POST /api/screenings
GET /api/screenings/{id}
#Image
POST /api/screenings/{id}/image
#Processing
POST /api/screenings/{id}/analyze
GET /api/screenings/{id}/status
#Results
GET /api/screenings/{id}/result
#Report
GET /api/screenings/{id}/report
#Review
POST /api/screenings/{id}/review
#9. ML Contract
Create an interface such as:
POST /ml/analyze
Input:
fundus image
Output:
{
"quality": {
"status": "ACCEPTABLE",
"confidence": 0.96
},
"dr": {
"grade": 3,
"referable": true,
"confidence": 0.91
},
"explainability": {
"gradcam_path": "...",
"annotated_image_path": "..."
},
"lesions": []
}
#10. Frontend pages
#1. Login
┌──────────────────────────┐
│ DR Screening │
│ │
│ Email │
│ [____________________] │
│ │
│ Password │
│ [____________________] │
│ │
│ [ Login ] │
└──────────────────────────┘
#2. Dashboard
Dashboard
Today's screenings 42
Pending reviews 7
Completed 35
Ungradable 3
[ New Screening ]
Recent screenings
─────────────────────────
Patient Status Grade
P-001 Complete 1
P-002 Review 3
P-003 Complete 0
#3. Patient
Patient
Patient ID: P-001
Name: ...
Age: ...
Sex: ...
[ Start New Screening ]
Previous screenings
#4. New screening
New Screening
Patient: P-001
Upload fundus image
┌────────────────────────┐
│ │
│ Drop image here │
│ │
└────────────────────────┘
[ Analyze ]
#5. Processing
Analyzing retinal image...
✓ Image uploaded
✓ Quality assessment
● DR analysis
○ Explainability
○ Report
#6. Results
SCREENING RESULT
┌───────────────────────────────┐
│ Fundus Image │
│ │
│ [ IMAGE ] │
└───────────────────────────────┘
DR Grade
Level 3
Referable DR
YES
Confidence
91%
────────────────────────────────
Explainability
[ Original ] [ Grad-CAM ] [ Annotated ]
────────────────────────────────
Lesion Evidence
Microaneurysms Detected
Exudates Detected
Hemorrhages Detected
────────────────────────────────
[ Review ] [ Generate Report ]
#11. The user flow
The whole application can then be thought of as one pipeline:
LOGIN
↓
DASHBOARD
↓
SELECT PATIENT
↓
NEW SCREENING
↓
UPLOAD FUNDUS IMAGE
↓
QUALITY CHECK
│
├──── UNGRADABLE
│ ↓
│ Recapture
│
└──── ACCEPTABLE
↓
ML ANALYSIS
↓
DR CLASSIFICATION
↓
EXPLAINABILITY
↓
RESULT
↓
┌───────┴────────┐
↓ ↓
Auto complete Human review
↓ ↓
└───────┬────────┘
↓
REPORT
#12. One important architectural decision
Avoid:
Frontend → ML
Use:
Frontend
↓
Backend
↓
ML
Because eventually the backend needs to handle:
- authentication
- patient information
- image storage
- model versions
- screening history
- audit trail
- reports
- human review
#13. Repository structure
dr-screening/
│
├── frontend/
│ ├── src/
│ ├── public/
│ └── README.md
│
├── backend/
│ ├── app/
│ │ ├── api/
│ │ ├── models/
│ │ ├── schemas/
│ │ ├── services/
│ │ ├── database/
│ │ └── main.py
│ │
│ └── tests/
│
├── ml/
│ └── README.md
│
├── storage/
│ └── .gitkeep
│
├── docs/
│ ├── architecture.md
│ ├── api.md
│ └── ml-contract.md
│
├── docker-compose.yml
└── README.md