UdasriHasindu commited on
Commit
d75ebed
·
1 Parent(s): 3190f06

docs: complete documentation

Browse files
Files changed (1) hide show
  1. README.md +296 -37
README.md CHANGED
@@ -7,34 +7,149 @@ sdk: docker
7
  app_port: 7860
8
  ---
9
 
10
- # 🧠 Parkinson's Motor Impairment Score API
11
 
12
- **FastAPI** backend that evaluates patient drawings (wave and spiral patterns) to detect and quantify motor impairments associated with Parkinson's disease.
13
 
14
- This service utilizes deep learning models (**VGG19** and **ResNet101**) automatically dynamically fetched from Hugging Face along with a custom OpenCV pre-processing pipeline to score severity precisely.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  ---
17
 
18
- ## 🚀 Features
19
- * **Lightning Fast:** Implements a FastAPI lifecycle manager to preload multi-hundred-megabyte machine learning models straight into RAM on server startup, ensuring 0-second prediction latency.
20
- * **Dual Classifiers:**
21
- * **Wave Patterns:** Analyzed via a VGG19 backbone.
22
- * **Spiral Patterns:** Analyzed via a ResNet101 backbone.
23
- * **Torch-less:** Fully replicates the original PyTorch training `torchvision` image transformation pipeline using strictly `numpy` and `cv2` for ultra-lightweight deployment.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  ---
26
 
27
- ## 🛠️ API Endpoints
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- ### 1. `POST /predict/wave`
30
- Accepts a drawn "wave" pattern image overlay and calculates severity.
31
 
32
- ### 2. `POST /predict/spiral`
33
- Accepts a drawn "spiral" pattern image overlay and calculates severity.
34
 
35
- **Input Format:** `multipart/form-data` with an image file.
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- **Response Example:**
38
  ```json
39
  {
40
  "drawing_type": "wave",
@@ -47,34 +162,178 @@ Accepts a drawn "spiral" pattern image overlay and calculates severity.
47
  }
48
  ```
49
 
 
 
 
 
 
 
 
 
 
 
50
  ---
51
 
52
- ## 💻 Local Development
53
 
54
- 1. **Create Virtual Environment:**
55
- ```bash
56
- python -m venv venv
57
- source venv/bin/activate
58
- ```
59
 
60
- 2. **Install Dependencies:**
61
- ```bash
62
- pip install -r requirements.txt
63
- pip install fastapi uvicorn python-multipart
64
- ```
65
 
66
- 3. **Run the Server:**
67
- ```bash
68
- uvicorn main:app --reload
69
- ```
70
 
71
- 4. Go to `http://127.0.0.1:8000/docs` to test the API directly using Swagger UI!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  ---
74
 
75
- ## ☁️ Hugging Face Deployment (Docker)
76
- This repository is pre-configured to automatically deploy as a **Docker Space** to Hugging Face via GitHub Actions.
77
 
78
- 1. Any changes pushed to the `main` branch trigger `.github/workflows/deploy.yml`
79
- 2. GitHub forcefully mirrors this repository to Hugging Face Hub securely using an injected `HF_TOKEN`.
80
- 3. Hugging Face reads the attached `Dockerfile` and dynamically exposes the FastAPI service on Port `7860`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  app_port: 7860
8
  ---
9
 
10
+ # Parkinson's Motor Impairment Score API
11
 
12
+ This project is a **FastAPI** service that predicts Parkinson's-related motor impairment from patient drawing images.
13
 
14
+ It accepts two drawing styles:
15
+
16
+ - **Wave drawings**
17
+ - **Spiral drawings**
18
+
19
+ Each image is preprocessed and passed into a deep learning model to produce:
20
+
21
+ - a raw model logit
22
+ - a sigmoid probability
23
+ - a normalized motor impairment score from 0 to 100
24
+ - a severity label
25
+ - a human-readable description
26
+
27
+ The project is designed for **local development**, **Docker deployment**, and **Hugging Face Spaces**.
28
+
29
+
30
+ The service is intended to:
31
+
32
+ 1. receive an uploaded image
33
+ 2. preprocess it consistently
34
+ 3. run inference using a pretrained model
35
+ 4. return a structured prediction response
36
+
37
+ ---
38
+
39
+ ## Key Features
40
+
41
+ ### 1. FastAPI-based service
42
+
43
+ The API uses FastAPI for fast request handling, automatic validation, and interactive documentation.
44
+
45
+ ### 2. Two prediction routes
46
+
47
+ - Wave drawings use a **VGG19-based** model
48
+ - Spiral drawings use a **ResNet101-based** model
49
+
50
+ ### 3. Startup model loading
51
+
52
+ Both models are loaded during application startup so the first request is faster.
53
+
54
+ ### 4. Custom preprocessing pipeline
55
+
56
+ The image pipeline reproduces the original training preprocessing using:
57
+
58
+ - OpenCV
59
+ - NumPy
60
+ - Pillow
61
+
62
+ ### 5. Hugging Face model download
63
+
64
+ The trained `.h5` models are downloaded from Hugging Face Hub when needed.
65
+
66
+ ### 6. CORS support
67
+
68
+ The API is configured to accept cross-origin requests from browser-based clients.
69
+
70
+ ### 7. Docker-ready deployment
71
+
72
+ The repository includes a Dockerfile for Hugging Face Spaces deployment.
73
 
74
  ---
75
 
76
+ ## Repository Structure
77
+
78
+ - [main.py](main.py) - FastAPI application entry point and API routes
79
+ - [services/predictor.py](services/predictor.py) - model loading, preprocessing, and prediction logic
80
+ - [services/**init**.py](services/__init__.py) - package initializer
81
+ - [requirements.txt](requirements.txt) - Python dependencies
82
+ - [Dockerfile](Dockerfile) - container configuration for deployment
83
+ - [.github/workflows/deploy.yml](.github/workflows/deploy.yml) - GitHub Actions workflow for deployment to Hugging Face
84
+ - [test/](test/) - sample images for testing and experimentation
85
+
86
+ ---
87
+
88
+ ## How the API Works
89
+
90
+ ### Request flow
91
+
92
+ 1. A client uploads a drawing image using multipart form data
93
+ 2. The API validates that the file is an image
94
+ 3. The image is converted into a consistent tensor-like NumPy array
95
+ 4. The correct model is loaded if not already cached
96
+ 5. The model returns a raw logit
97
+ 6. The logit is converted to a sigmoid probability
98
+ 7. The result is normalized into a motor impairment score
99
+ 8. A severity label and description are returned
100
+
101
+ ### Preprocessing pipeline
102
+
103
+ The preprocessing logic performs the following steps:
104
+
105
+ 1. load the image
106
+ 2. convert to grayscale
107
+ 3. apply Otsu thresholding with inversion
108
+ 4. resize to 224 × 224
109
+ 5. replicate grayscale into 3 channels
110
+ 6. apply normalization logic compatible with the training setup
111
+ 7. add a batch dimension
112
 
113
  ---
114
 
115
+ ## API Endpoints
116
+
117
+ ### Health check
118
+
119
+ **GET /**
120
+
121
+ Returns a simple status response.
122
+
123
+ Example response:
124
+
125
+ ```json
126
+ {
127
+ "status": "ok",
128
+ "message": "Welcome to the Motor Impairment Score API"
129
+ }
130
+ ```
131
+
132
+ ### Predict wave drawing
133
+
134
+ **POST /predict/wave**
135
 
136
+ Accepts a wave drawing image and returns a prediction.
 
137
 
138
+ ### Predict spiral drawing
 
139
 
140
+ **POST /predict/spiral**
141
+
142
+ Accepts a spiral drawing image and returns a prediction.
143
+
144
+ ### Input format
145
+
146
+ Both prediction endpoints expect:
147
+
148
+ - `multipart/form-data`
149
+ - a single file field named `file`
150
+
151
+ ### Example response
152
 
 
153
  ```json
154
  {
155
  "drawing_type": "wave",
 
162
  }
163
  ```
164
 
165
+ ### Response fields
166
+
167
+ - `drawing_type` - either `wave` or `spiral`
168
+ - `raw_logit` - raw model output before sigmoid
169
+ - `sigmoid_probability` - probability converted from the logit
170
+ - `motor_impairment_score` - normalized score between 0 and 100
171
+ - `severity_level` - severity category
172
+ - `description` - human-readable interpretation
173
+ - `is_parkinson` - boolean indicator derived from the severity level
174
+
175
  ---
176
 
177
+ ## Severity Levels
178
 
179
+ The API classifies the result into one of these labels:
 
 
 
 
180
 
181
+ - **Normal Pattern** - no motor impairment detected
182
+ - **Mild** - slight motor irregularities observed
183
+ - **Moderate** - noticeable motor impairment detected
184
+ - **High** - significant motor impairment observed
185
+ - **Severe** - strong Parkinsonian motor patterns detected
186
 
187
+ The exact score thresholds are defined in [services/predictor.py](services/predictor.py).
 
 
 
188
 
189
+ ---
190
+
191
+ ## Local Setup
192
+
193
+ ### 1. Create a virtual environment
194
+
195
+ ```bash
196
+ python -m venv venv
197
+ source venv/bin/activate
198
+ ```
199
+
200
+ ### 2. Install dependencies
201
+
202
+ ```bash
203
+ pip install -r requirements.txt
204
+ ```
205
+
206
+ If needed, also install the runtime packages used by the API:
207
+
208
+ ```bash
209
+ pip install fastapi uvicorn python-multipart
210
+ ```
211
+
212
+ ### 3. Run the server
213
+
214
+ ```bash
215
+ uvicorn main:app --reload
216
+ ```
217
+
218
+ ### 4. Open the documentation
219
+
220
+ Visit:
221
+
222
+ ```text
223
+ http://127.0.0.1:8000/docs
224
+ ```
225
+
226
+ This opens the interactive Swagger UI for testing the API.
227
+
228
+ ---
229
+
230
+ ## Example Requests
231
+
232
+ ### cURL example
233
+
234
+ ```bash
235
+ curl -X POST "http://127.0.0.1:8000/predict/wave" \
236
+ -F "file=@test/wave.png"
237
+ ```
238
+
239
+ ### Spiral example
240
+
241
+ ```bash
242
+ curl -X POST "http://127.0.0.1:8000/predict/spiral" \
243
+ -F "file=@test/spiral.png"
244
+ ```
245
+
246
+ ### Python example
247
+
248
+ ```python
249
+ import requests
250
+
251
+ url = "http://127.0.0.1:8000/predict/wave"
252
+
253
+ with open("test/wave.png", "rb") as f:
254
+ files = {"file": f}
255
+ response = requests.post(url, files=files)
256
+
257
+ print(response.json())
258
+ ```
259
 
260
  ---
261
 
 
 
262
 
263
+ ## Deployment
264
+
265
+ ### Docker
266
+
267
+ The repository contains a Dockerfile that:
268
+
269
+ - installs system dependencies required by OpenCV
270
+ - installs the Python dependencies
271
+ - runs the API on port `7860`
272
+
273
+ ### Hugging Face Spaces
274
+
275
+ The repository is set up for deployment as a Docker Space on Hugging Face.
276
+
277
+ Deployment flow:
278
+
279
+ 1. Push changes to the `main` branch
280
+ 2. GitHub Actions runs the workflow in [deploy.yml](.github/workflows/deploy.yml)
281
+ 3. The workflow pushes the repository to the Hugging Face Space repository
282
+ 4. Hugging Face rebuilds and redeploys the Space
283
+
284
+ Target Hugging Face repository:
285
+
286
+ `https://huggingface.co/spaces/xplorers/MIS_API`
287
+
288
+ ### Required secret
289
+
290
+ The GitHub Actions workflow needs this secret:
291
+
292
+ - `HF_TOKEN` - Hugging Face write token
293
+
294
+ Make sure the token has permission to push to the target Space.
295
+
296
+ ---
297
+
298
+ ## Important Files
299
+
300
+ ### [main.py](main.py)
301
+
302
+ Contains:
303
+
304
+ - the FastAPI app
305
+ - startup model loading
306
+ - CORS configuration
307
+ - image prediction endpoints
308
+
309
+ ### [services/predictor.py](services/predictor.py)
310
+
311
+ Contains:
312
+
313
+ - Hugging Face model download logic
314
+ - image preprocessing
315
+ - wave and spiral prediction functions
316
+ - severity interpretation logic
317
+
318
+ ### [Dockerfile](Dockerfile)
319
+
320
+ Contains:
321
+
322
+ - Python base image
323
+ - OpenCV system libraries
324
+ - application startup command
325
+
326
+ ### [.github/workflows/deploy.yml](.github/workflows/deploy.yml)
327
+
328
+ Contains:
329
+
330
+ - GitHub Actions deployment logic
331
+ - authenticated push to Hugging Face Spaces
332
+
333
+ ---
334
+
335
+ ## License and Usage
336
+
337
+ No explicit license file is currently included in the repository.
338
+
339
+ If you plan to publish or share the project publicly, add a license file and review the Hugging Face model and deployment permissions.