File size: 7,387 Bytes
89f2004
 
 
 
 
 
 
 
 
d75ebed
89f2004
d75ebed
89f2004
d75ebed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89f2004
 
 
d75ebed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89f2004
 
 
d75ebed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89f2004
d75ebed
89f2004
d75ebed
89f2004
d75ebed
 
 
 
 
 
 
 
 
 
 
 
89f2004
 
 
 
 
 
 
 
 
 
 
 
 
d75ebed
 
 
 
 
 
 
 
 
 
89f2004
 
d75ebed
89f2004
d75ebed
89f2004
d75ebed
 
 
 
 
89f2004
d75ebed
89f2004
d75ebed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89f2004
 
 
 
d75ebed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
---
title: Parkinson's Motor Impairment Predictor
emoji: 🧠
colorFrom: blue
colorTo: indigo
sdk: docker
app_port: 7860
---

# Parkinson's Motor Impairment Score API

This project is a **FastAPI** service that predicts Parkinson's-related motor impairment from patient drawing images.

It accepts two drawing styles:

- **Wave drawings**
- **Spiral drawings**

Each image is preprocessed and passed into a deep learning model to produce:

- a raw model logit
- a sigmoid probability
- a normalized motor impairment score from 0 to 100
- a severity label
- a human-readable description

The project is designed for **local development**, **Docker deployment**, and **Hugging Face Spaces**.


The service is intended to:

1. receive an uploaded image
2. preprocess it consistently
3. run inference using a pretrained model
4. return a structured prediction response

---

## Key Features

### 1. FastAPI-based service

The API uses FastAPI for fast request handling, automatic validation, and interactive documentation.

### 2. Two prediction routes

- Wave drawings use a **VGG19-based** model
- Spiral drawings use a **ResNet101-based** model

### 3. Startup model loading

Both models are loaded during application startup so the first request is faster.

### 4. Custom preprocessing pipeline

The image pipeline reproduces the original training preprocessing using:

- OpenCV
- NumPy
- Pillow

### 5. Hugging Face model download

The trained `.h5` models are downloaded from Hugging Face Hub when needed.

### 6. CORS support

The API is configured to accept cross-origin requests from browser-based clients.

### 7. Docker-ready deployment

The repository includes a Dockerfile for Hugging Face Spaces deployment.

---

## Repository Structure

- [main.py](main.py) - FastAPI application entry point and API routes
- [services/predictor.py](services/predictor.py) - model loading, preprocessing, and prediction logic
- [services/**init**.py](services/__init__.py) - package initializer
- [requirements.txt](requirements.txt) - Python dependencies
- [Dockerfile](Dockerfile) - container configuration for deployment
- [.github/workflows/deploy.yml](.github/workflows/deploy.yml) - GitHub Actions workflow for deployment to Hugging Face
- [test/](test/) - sample images for testing and experimentation

---

## How the API Works

### Request flow

1. A client uploads a drawing image using multipart form data
2. The API validates that the file is an image
3. The image is converted into a consistent tensor-like NumPy array
4. The correct model is loaded if not already cached
5. The model returns a raw logit
6. The logit is converted to a sigmoid probability
7. The result is normalized into a motor impairment score
8. A severity label and description are returned

### Preprocessing pipeline

The preprocessing logic performs the following steps:

1. load the image
2. convert to grayscale
3. apply Otsu thresholding with inversion
4. resize to 224 × 224
5. replicate grayscale into 3 channels
6. apply normalization logic compatible with the training setup
7. add a batch dimension

---

## API Endpoints

### Health check

**GET /**

Returns a simple status response.

Example response:

```json
{
  "status": "ok",
  "message": "Welcome to the Motor Impairment Score API"
}
```

### Predict wave drawing

**POST /predict/wave**

Accepts a wave drawing image and returns a prediction.

### Predict spiral drawing

**POST /predict/spiral**

Accepts a spiral drawing image and returns a prediction.

### Input format

Both prediction endpoints expect:

- `multipart/form-data`
- a single file field named `file`

### Example response

```json
{
  "drawing_type": "wave",
  "raw_logit": 8.7809,
  "sigmoid_probability": 0.9998,
  "motor_impairment_score": 43.98,
  "severity_level": "Mild",
  "description": "Slight motor irregularities observed.",
  "is_parkinson": true
}
```

### Response fields

- `drawing_type` - either `wave` or `spiral`
- `raw_logit` - raw model output before sigmoid
- `sigmoid_probability` - probability converted from the logit
- `motor_impairment_score` - normalized score between 0 and 100
- `severity_level` - severity category
- `description` - human-readable interpretation
- `is_parkinson` - boolean indicator derived from the severity level

---

## Severity Levels

The API classifies the result into one of these labels:

- **Normal Pattern** - no motor impairment detected
- **Mild** - slight motor irregularities observed
- **Moderate** - noticeable motor impairment detected
- **High** - significant motor impairment observed
- **Severe** - strong Parkinsonian motor patterns detected

The exact score thresholds are defined in [services/predictor.py](services/predictor.py).

---

## Local Setup

### 1. Create a virtual environment

```bash
python -m venv venv
source venv/bin/activate
```

### 2. Install dependencies

```bash
pip install -r requirements.txt
```

If needed, also install the runtime packages used by the API:

```bash
pip install fastapi uvicorn python-multipart
```

### 3. Run the server

```bash
uvicorn main:app --reload
```

### 4. Open the documentation

Visit:

```text
http://127.0.0.1:8000/docs
```

This opens the interactive Swagger UI for testing the API.

---

## Example Requests

### cURL example

```bash
curl -X POST "http://127.0.0.1:8000/predict/wave" \
   -F "file=@test/wave.png"
```

### Spiral example

```bash
curl -X POST "http://127.0.0.1:8000/predict/spiral" \
   -F "file=@test/spiral.png"
```

### Python example

```python
import requests

url = "http://127.0.0.1:8000/predict/wave"

with open("test/wave.png", "rb") as f:
      files = {"file": f}
      response = requests.post(url, files=files)

print(response.json())
```

---


## Deployment

### Docker

The repository contains a Dockerfile that:

- installs system dependencies required by OpenCV
- installs the Python dependencies
- runs the API on port `7860`

### Hugging Face Spaces

The repository is set up for deployment as a Docker Space on Hugging Face.

Deployment flow:

1. Push changes to the `main` branch
2. GitHub Actions runs the workflow in [deploy.yml](.github/workflows/deploy.yml)
3. The workflow pushes the repository to the Hugging Face Space repository
4. Hugging Face rebuilds and redeploys the Space

Target Hugging Face repository:

`https://huggingface.co/spaces/xplorers/MIS_API`

### Required secret

The GitHub Actions workflow needs this secret:

- `HF_TOKEN` - Hugging Face write token

Make sure the token has permission to push to the target Space.

---

## Important Files

### [main.py](main.py)

Contains:

- the FastAPI app
- startup model loading
- CORS configuration
- image prediction endpoints

### [services/predictor.py](services/predictor.py)

Contains:

- Hugging Face model download logic
- image preprocessing
- wave and spiral prediction functions
- severity interpretation logic

### [Dockerfile](Dockerfile)

Contains:

- Python base image
- OpenCV system libraries
- application startup command

### [.github/workflows/deploy.yml](.github/workflows/deploy.yml)

Contains:

- GitHub Actions deployment logic
- authenticated push to Hugging Face Spaces

---

## License and Usage

No explicit license file is currently included in the repository.

If you plan to publish or share the project publicly, add a license file and review the Hugging Face model and deployment permissions.