--- title: UPDRS API emoji: 🧠 colorFrom: blue colorTo: purple sdk: docker app_port: 7860 pinned: false --- # Parkinson's Disease Motor UPDRS Prediction API A production-style FastAPI service that predicts **motor UPDRS score** from a voice sample and patient metadata. The service: - accepts audio uploads (`wav`, `mp3`, `ogg`, `webm`), - converts them to WAV when needed, - extracts clinical voice biomarkers using Praat, - loads a trained ensemble model from Hugging Face, - returns a numeric UPDRS motor prediction. --- ## 1) What this API does Given: - `age` - `sex` (`male` or `female`) - `test_time` - `audio_file` The API returns: - `prediction` (float): estimated motor UPDRS score. --- ## 2) Project structure ```text UPDRS_API/ ├── main.py ├── requirements.txt ├── Dockerfile ├── README.md ├── routers/ │ └── analyze_router.py ├── services/ │ └── voice_analyze_service.py ├── ml/ │ └── model_predictor.py ├── utils/ │ ├── file_handler.py │ └── voice_data_extraction.py └── schema/ └── patient_inputs.py ``` ### Responsibilities - **main.py**: app startup, CORS, lifespan hook, route registration. - **routers/analyze_router.py**: request validation and endpoint definitions. - **services/voice_analyze_service.py**: end-to-end orchestration. - **utils/file_handler.py**: upload persistence + ffmpeg conversion. - **utils/voice_data_extraction.py**: Praat/parselmouth feature extraction. - **ml/model_predictor.py**: model download/cache and inference. --- ## 3) API endpoints | Method | Path | Purpose | | ------ | ---------------- | -------------------------------------------- | | GET | `/` | Basic welcome/status message | | GET | `/health` | Health + model cache state | | POST | `/analyze/test` | Echo/debug endpoint for multipart form input | | POST | `/analyze/voice` | Main prediction endpoint | ### `GET /health` response ```json { "status": "ok", "models_loaded": true } ``` --- ## 4) Main prediction endpoint ### `POST /analyze/voice` Content type: `multipart/form-data` | Field | Type | Validation | | ------------ | ------ | ------------------ | | `age` | int | `10 < age < 120` | | `sex` | string | `male` or `female` | | `test_time` | float | `> 0` | | `audio_file` | file | required | ### Example response ```json { "prediction": 18.42 } ``` --- ## 5) How prediction works (pipeline) 1. Request arrives at `POST /analyze/voice`. 2. Audio file is written to a temp file. 3. Non-WAV formats are converted to WAV via `ffmpeg`. 4. Praat/parselmouth extracts acoustic and nonlinear features. 5. `sex` is encoded (`male=1`, `female=0`). 6. Features are combined with `age` and `test_time`. 7. Features are ordered/scaled according to `feature_names.pkl` and `scaler.pkl`. 8. Ensemble model predicts UPDRS. 9. Temp file is always cleaned up. --- ## 6) Extracted voice features The service extracts these features: - **Jitter** - `Jitter(%)` - `Jitter(Abs)` - `Jitter:RAP` - `Jitter:PPQ5` - `Jitter:DDP` - **Shimmer** - `Shimmer` - `Shimmer(dB)` - `Shimmer:APQ3` - `Shimmer:APQ5` - `Shimmer:APQ11` - `Shimmer:DDA` - **Noise/Harmonics** - `NHR` - `HNR` - **Nonlinear dynamics** - `RPDE` - `DFA` - `PPE` --- ## 7) Model details - Model repo: https://huggingface.co/xplorers/parkinsons-updrs-model - Artifacts downloaded on startup: - `ensemble_model.pkl` - `feature_names.pkl` - `scaler.pkl` - Models are cached in-memory (`_cache`) after first load. --- ## 8) Environment variables Create a `.env` file in the project root (optional but recommended): ```env HF_TOKEN=your_huggingface_access_token ``` `main.py` calls `load_dotenv()`, so `.env` is loaded automatically. --- ## 9) Local development setup ### Prerequisites - Python 3.11+ (recommended for this codebase) - `ffmpeg` installed and available in PATH ### Install ```bash python -m venv venv source venv/bin/activate pip install -r requirements.txt ``` ### Run ```bash uvicorn main:app --reload --host 0.0.0.0 --port 8000 ``` Open: - Swagger UI: http://127.0.0.1:8000/docs - ReDoc: http://127.0.0.1:8000/redoc --- ## 10) Docker usage Build image: ```bash docker build -t updrs-api . ``` Run container: ```bash docker run --rm -p 7860:7860 --env HF_TOKEN=$HF_TOKEN updrs-api ``` Container entrypoint uses: ```bash uvicorn main:app --host 0.0.0.0 --port 7860 ``` --- ## 11) cURL examples ### Health check ```bash curl http://127.0.0.1:8000/health ``` ### Voice prediction ```bash curl -X POST "http://127.0.0.1:8000/analyze/voice" \ -F "age=63" \ -F "sex=male" \ -F "test_time=12.5" \ -F "audio_file=@./sample.wav" ``` --- ## 12) Error handling and troubleshooting ### 401 Unauthorized from Hugging Face Cause: gated/private model repository. Fix: 1. Ensure your account has access to the model page. 2. Set `HF_TOKEN` in environment or `.env`. 3. Restart the API. ### `ffmpeg` conversion failure Cause: `ffmpeg` missing or unsupported input file. Fix: - Install `ffmpeg` (system package). - Test source file manually with `ffmpeg -i `. ### Models not loaded `predict_parkinson()` raises runtime error if startup download failed. Fix: - Check server startup logs. - Verify internet access and token permissions. --- ## 13) License This project includes a `LICENSE` file at the repository root. Review it before distribution or production use.