Abdullah1211 commited on
Commit
dde96e3
·
verified ·
1 Parent(s): 39a60c6

Upload 5 files

Browse files
Files changed (3) hide show
  1. README.md +151 -75
  2. app.py +411 -161
  3. model.joblib +1 -1
README.md CHANGED
@@ -1,75 +1,151 @@
1
-
2
- # Parkinson's Disease Detection API
3
-
4
- This API provides predictions for detecting Parkinson's disease based on voice recordings.
5
-
6
- ## Overview
7
-
8
- The model analyzes 22 acoustic features extracted from sustained phonations (holding the sound 'ahhh'),
9
- including jitter, shimmer, and various voice measures to predict if the voice sample indicates Parkinson's disease.
10
-
11
- ## API Usage
12
-
13
- ### Endpoint: `/api/predict`
14
-
15
- Send a POST request with the following acoustic parameters (all are optional, defaults will be used for missing values):
16
-
17
- - `fo_hz`: Fundamental frequency (Hz)
18
- - `fhi_hz`: Maximum fundamental frequency (Hz)
19
- - `flo_hz`: Minimum fundamental frequency (Hz)
20
- - `jitter_percent`: Relative jitter percentage
21
- - `jitter_abs`: Absolute jitter in microseconds
22
- - `rap`: Relative amplitude perturbation
23
- - `ppq`: Five-point period perturbation quotient
24
- - `ddp`: Average absolute difference of differences between jitter cycles
25
- - `shimmer`: Local shimmer
26
- - `shimmer_db`: Shimmer in decibels
27
- - `apq3`: Three-point amplitude perturbation quotient
28
- - `apq5`: Five-point amplitude perturbation quotient
29
- - `apq`: 11-point amplitude perturbation quotient
30
- - `dda`: Average absolute differences between consecutive differences of amplitudes
31
- - `nhr`: Noise-to-harmonics ratio
32
- - `hnr`: Harmonics-to-noise ratio
33
- - `rpde`: Recurrence period density entropy measure
34
- - `dfa`: Signal fractal scaling exponent
35
- - `spread1`: Nonlinear measure of fundamental frequency variation
36
- - `spread2`: Nonlinear measure of fundamental frequency variation
37
- - `d2`: Correlation dimension
38
- - `ppe`: Pitch period entropy
39
-
40
- ### Response
41
-
42
- The API returns a JSON object with:
43
-
44
- - `prediction`: Binary classification (0 = healthy, 1 = Parkinson's)
45
- - `prediction_label`: Text description of the prediction
46
- - `confidence`: Model confidence in the prediction (0-1)
47
- - `using_model`: Whether the ML model was used or fallback logic
48
- - `execution_time_ms`: Execution time in milliseconds
49
- - `model_type`: Type of model used (SVM or Fallback)
50
-
51
- ## Example
52
-
53
- ```python
54
- import requests
55
-
56
- url = "https://yourusername-parkinsons-model.hf.space/api/predict"
57
- data = {
58
- "fo_hz": 120.0,
59
- "fhi_hz": 150.0,
60
- "flo_hz": 100.0,
61
- "jitter_percent": 0.009,
62
- "shimmer": 0.05,
63
- "hnr": 19.0
64
- }
65
-
66
- response = requests.post(url, data=data)
67
- result = response.json()
68
- print(result)
69
- ```
70
-
71
- ## Model Information
72
-
73
- - Model Type: Support Vector Machine (SVM)
74
- - Accuracy: ~87%
75
- - Dataset: UCI ML Parkinson's Dataset
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # BrainWise
2
+
3
+ BrainWise is a comprehensive web application designed to help users with brain health monitoring, stroke prediction, and cognitive enhancement through health tracking, personalized goals, and educational resources.
4
+
5
+ ## 🧠 Features
6
+
7
+ - **Health Metrics Tracking**: Monitor vital signs and health indicators that affect brain health
8
+ - **Stroke Risk Prediction**: AI-powered stroke risk assessment using machine learning models
9
+ - **Brain Scan Analysis**: Detect brain tumors and Alzheimer's disease from MRI scans
10
+ - **Research & Studies**: Access to latest peer-reviewed research on brain health and stroke prevention
11
+ - **Educational Resources**: Curated guides and video content from trusted sources
12
+ - **Cognitive Training Tools**: Interactive exercises for brain health improvement
13
+ - **Data Visualization**: View your progress through interactive charts and visualizations
14
+
15
+ ## 🚀 Getting Started
16
+
17
+ ### Prerequisites
18
+
19
+ - Node.js 18+
20
+ - npm or yarn
21
+ - MongoDB instance (local or Atlas)
22
+ - Uploadcare account (for image handling)
23
+ - Hugging Face account (for ML model hosting)
24
+
25
+ ### Installation
26
+
27
+ 1. Clone the repository
28
+ ```bash
29
+ git clone https://github.com/AbdullahSaeed1211/brainwise.git
30
+ cd brainwise
31
+ ```
32
+
33
+ 2. Install dependencies
34
+ ```bash
35
+ npm install
36
+ # or
37
+ yarn install
38
+ ```
39
+
40
+ 3. Set up environment variables
41
+ ```
42
+ # Create a .env.local file with the following variables
43
+ MONGODB_URI=your_mongodb_connection_string
44
+ NEXT_PUBLIC_UPLOADCARE_PUBLIC_KEY=your_uploadcare_public_key
45
+ UPLOADCARE_SECRET_KEY=your_uploadcare_secret_key
46
+ SEMANTIC_SCHOLAR_API_KEY=your_api_key
47
+ ```
48
+
49
+ 4. Run the development server
50
+ ```bash
51
+ npm run dev
52
+ # or
53
+ yarn dev
54
+ ```
55
+
56
+ 5. Open [http://localhost:3000](http://localhost:3000) in your browser
57
+
58
+ ## 📚 Documentation
59
+
60
+ Detailed documentation can be found in the `/docs` directory:
61
+
62
+ - [Architecture Overview](docs/architecture-overview.md)
63
+ - [Authentication System](docs/authentication-system.md)
64
+ - [Health Metrics System](docs/health-metrics-system.md)
65
+ - [ML Model Hosting](docs/ml-hosting-architecture.md)
66
+ - [Brain Scan Analysis](docs/ml-hosting-guide.md)
67
+ - [Data Visualization](docs/data-visualization.md)
68
+ - [Research Integration](docs/research-integration.md)
69
+
70
+ ## 🧩 Project Structure
71
+
72
+ ```
73
+ brainwise/
74
+ ├── app/ # Next.js 14 App Router pages & API routes
75
+ │ ├── api/ # API routes for ML models and data
76
+ │ ├���─ predictors/ # Brain scan analysis tools (tumor, alzheimers)
77
+ │ ├── research/ # Research papers and studies
78
+ │ ├── tools/ # Brain health tools and assessments
79
+ │ └── dashboard/ # User dashboard and metrics
80
+ ├── components/ # React components
81
+ │ ├── ui/ # Shadcn UI components
82
+ │ ├── charts/ # Data visualization components
83
+ │ └── forms/ # Form components
84
+ ├── lib/ # Utility functions and shared logic
85
+ ├── public/ # Static assets
86
+ ├── types/ # TypeScript type definitions
87
+ └── docs/ # Documentation
88
+ ```
89
+
90
+ ## 🔧 Technology Stack
91
+
92
+ - **Frontend**: Next.js 14, React, TypeScript, Tailwind CSS, Shadcn UI
93
+ - **Backend**: Next.js API Routes, MongoDB
94
+ - **Machine Learning**: Hugging Face Spaces, TensorFlow.js
95
+ - **Image Handling**: Uploadcare CDN
96
+ - **Research API**: Semantic Scholar API
97
+ - **Visualization**: Recharts, Framer Motion
98
+ - **Authentication**: Custom auth (with plans to migrate to Clerk)
99
+
100
+ ## 🌱 Development Roadmap
101
+
102
+ - [x] Health metrics tracking system
103
+ - [x] Stroke risk prediction model
104
+ - [x] Brain tumor detection model
105
+ - [x] Alzheimer's detection model
106
+ - [x] Research paper integration
107
+ - [x] Educational resources
108
+ - [x] Cognitive training tools
109
+ - [ ] Advanced data analytics dashboard
110
+ - [ ] Mobile optimization
111
+ - [ ] Newsletter system
112
+
113
+ ## 🔒 Security & Privacy
114
+
115
+ BrainWise prioritizes the security and privacy of health data:
116
+
117
+ - All health data is associated with user IDs
118
+ - Authentication required for all sensitive operations
119
+ - Medical images are securely stored using Uploadcare's HIPAA-compliant storage
120
+ - No third-party access to health information
121
+ - HIPAA-informed practices for handling sensitive data
122
+ - Secure API key management
123
+
124
+ ## 🤝 Contributing
125
+
126
+ Contributions are welcome! Please feel free to submit a Pull Request.
127
+
128
+ 1. Fork the repository
129
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
130
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
131
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
132
+ 5. Open a Pull Request
133
+
134
+ ## 📄 License
135
+
136
+ This project is licensed under the MIT License - see the LICENSE file for details.
137
+
138
+ ## 📱 Contact
139
+
140
+ Project Link: [https://github.com/AbdullahSaeed1211/brainwise](https://github.com/AbdullahSaeed1211/brainwise)
141
+
142
+ ## 🙏 Acknowledgements
143
+
144
+ - [Next.js](https://nextjs.org/)
145
+ - [Tailwind CSS](https://tailwindcss.com/)
146
+ - [Shadcn UI](https://ui.shadcn.com/)
147
+ - [Uploadcare](https://uploadcare.com/)
148
+ - [Hugging Face](https://huggingface.co/)
149
+ - [Recharts](https://recharts.org/)
150
+ - [Semantic Scholar](https://www.semanticscholar.org/)
151
+ - [TensorFlow.js](https://www.tensorflow.org/js)
app.py CHANGED
@@ -1,183 +1,433 @@
1
-
2
- import joblib
3
- import pandas as pd
4
  import numpy as np
5
- from fastapi import FastAPI, Form, Request
6
- from fastapi.responses import JSONResponse
7
- from fastapi.middleware.cors import CORSMiddleware
8
- from pydantic import BaseModel
9
- from typing import Optional
10
  import time
 
11
  import os
 
 
 
 
 
 
12
 
13
- # Load model
14
- print("Loading Parkinson's Disease detection model...")
15
- model_path = "/app/model.joblib"
16
- print(f"Model file exists: {os.path.exists(model_path)}")
17
- print(f"Model file size: {os.path.getsize(model_path) / 1024:.2f} KB")
18
-
19
- try:
20
- model_package = joblib.load(model_path)
21
- print("Model loaded successfully!")
22
- model = model_package['model']
23
- scaler = model_package['scaler']
24
- feature_names = model_package['feature_names']
25
- print(f"Model details: Type: {type(model)}")
26
- print(f"Number of features: {len(feature_names)}")
27
- except Exception as e:
28
- print(f"Error loading model: {e}")
29
- model_package = None
30
-
31
- # Create FastAPI app
32
- app = FastAPI(title="Parkinson's Disease Detection API")
33
 
34
- # Add CORS middleware
35
- app.add_middleware(
36
- CORSMiddleware,
37
- allow_origins=["*"],
38
- allow_credentials=True,
39
- allow_methods=["*"],
40
- allow_headers=["*"],
41
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- # Define a class for the request body
44
- class ParkinsonsInput(BaseModel):
45
- fo_hz: float
46
- fhi_hz: float
47
- flo_hz: float
48
- jitter_percent: float
49
- jitter_abs: float
50
- rap: float
51
- ppq: float
52
- ddp: float
53
- shimmer: float
54
- shimmer_db: float
55
- apq3: float
56
- apq5: float
57
- apq: float
58
- dda: float
59
- nhr: float
60
- hnr: float
61
- rpde: float
62
- dfa: float
63
- spread1: float
64
- spread2: float
65
- d2: float
66
- ppe: float
67
-
68
- @app.post("/api/predict")
69
- async def predict_parkinsons(
70
- fo_hz: Optional[float] = Form(None),
71
- fhi_hz: Optional[float] = Form(None),
72
- flo_hz: Optional[float] = Form(None),
73
- jitter_percent: Optional[float] = Form(None),
74
- jitter_abs: Optional[float] = Form(None),
75
- rap: Optional[float] = Form(None),
76
- ppq: Optional[float] = Form(None),
77
- ddp: Optional[float] = Form(None),
78
- shimmer: Optional[float] = Form(None),
79
- shimmer_db: Optional[float] = Form(None),
80
- apq3: Optional[float] = Form(None),
81
- apq5: Optional[float] = Form(None),
82
- apq: Optional[float] = Form(None),
83
- dda: Optional[float] = Form(None),
84
- nhr: Optional[float] = Form(None),
85
- hnr: Optional[float] = Form(None),
86
- rpde: Optional[float] = Form(None),
87
- dfa: Optional[float] = Form(None),
88
- spread1: Optional[float] = Form(None),
89
- spread2: Optional[float] = Form(None),
90
- d2: Optional[float] = Form(None),
91
- ppe: Optional[float] = Form(None)
92
- ):
93
- start_time = time.time()
94
 
95
- # Create a dictionary from the input parameters
96
- input_data = {
97
- 'MDVP:Fo(Hz)': fo_hz or 119.992,
98
- 'MDVP:Fhi(Hz)': fhi_hz or 157.302,
99
- 'MDVP:Flo(Hz)': flo_hz or 74.997,
100
- 'MDVP:Jitter(%)': jitter_percent or 0.00784,
101
- 'MDVP:Jitter(Abs)': jitter_abs or 0.00007,
102
- 'MDVP:RAP': rap or 0.00370,
103
- 'MDVP:PPQ': ppq or 0.00554,
104
- 'Jitter:DDP': ddp or 0.01109,
105
- 'MDVP:Shimmer': shimmer or 0.04374,
106
- 'MDVP:Shimmer(dB)': shimmer_db or 0.426,
107
- 'Shimmer:APQ3': apq3 or 0.02182,
108
- 'Shimmer:APQ5': apq5 or 0.02971,
109
- 'MDVP:APQ': apq or 0.02971,
110
- 'Shimmer:DDA': dda or 0.06545,
111
- 'NHR': nhr or 0.02211,
112
- 'HNR': hnr or 21.033,
113
- 'RPDE': rpde or 0.414783,
114
- 'DFA': dfa or 0.815285,
115
- 'spread1': spread1 or -4.813031,
116
- 'spread2': spread2 or 0.266482,
117
- 'D2': d2 or 2.301442,
118
- 'PPE': ppe or 0.284654
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
 
121
- print("Received data:", input_data)
 
 
 
 
122
 
123
  try:
124
- if model_package is None:
125
- raise ValueError("Model not loaded")
126
-
127
- # Convert to DataFrame and ensure column order
128
- input_df = pd.DataFrame([input_data])
129
- input_df = input_df[feature_names] # Reorder columns to match training data
130
-
131
- # Standardize the input data
132
- input_scaled = scaler.transform(input_df)
133
-
134
- # Make prediction
135
- prediction = model.predict(input_scaled)[0]
136
- prediction_proba = model.predict_proba(input_scaled)[0]
137
-
138
- # Interpretation
139
- result = {
140
- "prediction": int(prediction),
141
- "prediction_label": "Parkinson's Disease" if prediction == 1 else "Healthy",
142
- "confidence": float(prediction_proba[int(prediction)]),
143
- "using_model": True,
144
- "execution_time_ms": (time.time() - start_time) * 1000,
145
- "model_type": "SVM"
146
- }
147
 
 
 
 
 
 
 
 
148
  except Exception as e:
149
- print("Error in prediction:", e)
150
-
151
- # Fallback calculation - basic rule-based
152
- # Higher shimmer and jitter values, low HNR often indicate Parkinson's
153
- high_jitter = input_data['MDVP:Jitter(%)'] > 0.008
154
- high_shimmer = input_data['MDVP:Shimmer'] > 0.05
155
- low_hnr = input_data['HNR'] < 20
 
 
 
 
 
156
 
157
- # Count risk factors
158
- risk_factors = sum([high_jitter, high_shimmer, low_hnr])
159
 
160
- # Simple fallback prediction
161
- fallback_prediction = 1 if risk_factors >= 2 else 0
162
- fallback_confidence = 0.5 + (risk_factors * 0.1) # Simple scaling
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
- result = {
165
- "prediction": fallback_prediction,
166
- "prediction_label": "Parkinson's Disease" if fallback_prediction == 1 else "Healthy",
167
- "confidence": float(fallback_confidence),
168
- "using_model": False,
169
- "execution_time_ms": (time.time() - start_time) * 1000,
170
- "model_type": "Fallback"
171
- }
172
-
173
- print("Prediction result:", result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  return result
175
 
176
- @app.get("/")
177
- async def root():
178
- return {"message": "Parkinson's Disease Detection API is running! Use /api/predict endpoint for predictions."}
179
 
180
- # Run the application
181
  if __name__ == "__main__":
182
  import uvicorn
183
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
+ import gradio as gr
 
 
2
  import numpy as np
3
+ import pandas as pd
 
 
 
 
4
  import time
5
+ import random
6
  import os
7
+ import joblib
8
+ from sklearn.ensemble import RandomForestClassifier
9
+ from sklearn.preprocessing import StandardScaler
10
+ from fastapi import FastAPI, Query
11
+ from pydantic import BaseModel
12
+ from typing import Optional, List, Dict, Any, Union
13
 
14
+ # Define model paths - try both Hugging Face and local paths
15
+ hf_model_path = "/app/model.joblib"
16
+ local_model_path = "model.joblib"
17
+ current_dir_model_path = "./model.joblib"
18
+ relative_model_path = "hf-spaces/parkinsons-model/model.joblib"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ print("Loading Parkinson's disease prediction model...")
21
+ # Try to load the model from various paths
22
+ for path in [hf_model_path, local_model_path, current_dir_model_path, relative_model_path]:
23
+ try:
24
+ if os.path.exists(path):
25
+ print(f"Found model at: {path}")
26
+ model_package = joblib.load(path)
27
+ model = model_package['model']
28
+ scaler = model_package['scaler']
29
+ feature_names = model_package.get('feature_names', [])
30
+
31
+ # Check if it's our model or the UCI Parkinson's dataset model
32
+ is_uci_model = len(feature_names) > 0 and 'MDVP:Fo(Hz)' in feature_names[0]
33
+
34
+ if is_uci_model:
35
+ print("Loaded UCI Parkinson's dataset model.")
36
+ else:
37
+ print("Loaded custom Parkinson's risk model.")
38
+
39
+ using_trained_model = True
40
+ print("Pre-trained model loaded successfully!")
41
+ break
42
+ except Exception as e:
43
+ print(f"Could not load model from {path}: {e}")
44
+ else:
45
+ # No model found, create a fallback
46
+ print("No model found. Creating fallback model.")
47
+ model = RandomForestClassifier(n_estimators=100, random_state=42)
48
+ using_trained_model = False
49
+
50
+ # Generate mock data for training
51
+ np.random.seed(42)
52
+
53
+ # Generate synthetic data
54
+ X_mock = pd.DataFrame({
55
+ 'age': np.random.uniform(40, 85, 500),
56
+ 'tremor': np.random.choice([0, 1], size=500, p=[0.3, 0.7]),
57
+ 'stiffness': np.random.choice([0, 1], size=500, p=[0.4, 0.6]),
58
+ 'balance_problems': np.random.choice([0, 1], size=500, p=[0.5, 0.5]),
59
+ 'slow_movement': np.random.choice([0, 1], size=500, p=[0.4, 0.6]),
60
+ 'sleep_issues': np.random.choice([0, 1], size=500, p=[0.7, 0.3]),
61
+ 'tremor_severity': np.random.uniform(0, 10, 500),
62
+ 'family_history': np.random.choice([0, 1], size=500, p=[0.8, 0.2]),
63
+ 'symptom_duration': np.random.uniform(0, 60, 500),
64
+ 'gender_Male': np.random.choice([0, 1], size=500)
65
+ })
66
+
67
+ # Create a simple rule-based target
68
+ prob = (X_mock['age'] > 70).astype(int) * 0.2 + \
69
+ X_mock['tremor'] * 0.2 + \
70
+ X_mock['stiffness'] * 0.15 + \
71
+ X_mock['balance_problems'] * 0.1 + \
72
+ X_mock['slow_movement'] * 0.2 + \
73
+ X_mock['gender_Male'] * 0.05 + \
74
+ X_mock['family_history'] * 0.1 + \
75
+ (X_mock['symptom_duration'] > 24).astype(int) * 0.1
76
+
77
+ y_mock = (prob > 0.5).astype(int)
78
+
79
+ # Fit the model
80
+ scaler = StandardScaler()
81
+ X_scaled = scaler.fit_transform(X_mock)
82
+ model.fit(X_scaled, y_mock)
83
+ feature_names = X_mock.columns.tolist()
84
 
85
+ print("Model loaded successfully!")
86
+
87
+ def calculate_risk_factors(data):
88
+ risk_factors = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
+ # Age is a risk factor
91
+ if data['age'] > 80:
92
+ risk_factors.append("Advanced age (80+)")
93
+ elif data['age'] > 65:
94
+ risk_factors.append("Senior age (65+)")
95
+ elif data['age'] > 55:
96
+ risk_factors.append("Higher age risk (55+)")
97
+
98
+ # Symptoms
99
+ if data['tremor'] == 1:
100
+ risk_factors.append("Presence of tremor")
101
+
102
+ if data['tremor_severity'] > 7:
103
+ risk_factors.append("Severe tremor")
104
+ elif data['tremor_severity'] > 4:
105
+ risk_factors.append("Moderate tremor")
106
+
107
+ if data['tremor_frequency'] == "constant":
108
+ risk_factors.append("Constant tremor")
109
+ elif data['tremor_frequency'] == "frequent":
110
+ risk_factors.append("Frequent tremor")
111
+
112
+ if data['stiffness'] == 1:
113
+ risk_factors.append("Muscle stiffness")
114
+
115
+ if data['balance_problems'] == 1:
116
+ risk_factors.append("Balance problems")
117
+
118
+ if data['slow_movement'] == 1:
119
+ risk_factors.append("Slowness of movement (bradykinesia)")
120
+
121
+ if data.get('sleep_issues', 0) == 1:
122
+ risk_factors.append("Sleep disturbances")
123
+
124
+ # Family history
125
+ if data['family_history'] == 1:
126
+ risk_factors.append("Family history of Parkinson's disease")
127
+
128
+ # Symptom duration
129
+ if data['symptom_duration'] > 36:
130
+ risk_factors.append("Long-standing symptoms (3+ years)")
131
+ elif data['symptom_duration'] > 12:
132
+ risk_factors.append("Sustained symptoms (1+ year)")
133
+
134
+ # Gender factor
135
+ if data['gender'] == "Male":
136
+ risk_factors.append("Male gender (higher risk)")
137
+
138
+ return risk_factors
139
+
140
+ def process_input_data(data):
141
+ # Create a feature vector from the input data
142
+ X_test = {
143
+ 'age': float(data['age']),
144
+ 'tremor': int(data['tremor']),
145
+ 'stiffness': int(data['stiffness']),
146
+ 'balance_problems': int(data['balance_problems']),
147
+ 'slow_movement': int(data['slow_movement']),
148
+ 'sleep_issues': int(data.get('sleep_issues', 0)),
149
+ 'tremor_severity': float(data['tremor_severity']),
150
+ 'family_history': int(data['family_history']),
151
+ 'symptom_duration': float(data['symptom_duration']),
152
+ 'gender_Male': 1 if data['gender'] == 'Male' else 0
153
  }
154
 
155
+ # Convert to DataFrame for easy processing
156
+ X_test_df = pd.DataFrame([X_test])
157
+
158
+ # Scale the test data (use the appropriate scaler)
159
+ X_test_scaled = scaler.transform(X_test_df)
160
 
161
  try:
162
+ # Get model predictions
163
+ prediction_proba = model.predict_proba(X_test_scaled)[0][1]
164
+ prediction_class = int(prediction_proba > 0.5)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
+ # Determine risk level
167
+ if prediction_proba > 0.6:
168
+ risk_level = "High Risk"
169
+ elif prediction_proba > 0.3:
170
+ risk_level = "Moderate Risk"
171
+ else:
172
+ risk_level = "Low Risk"
173
  except Exception as e:
174
+ print(f"Error in prediction: {e}")
175
+ # Fallback to a simple calculation if the model fails
176
+ risk_score = sum([
177
+ 1 if data['age'] > 70 else 0,
178
+ 1 if data['tremor'] == 1 else 0,
179
+ 1 if data['stiffness'] == 1 else 0,
180
+ 1 if data['balance_problems'] == 1 else 0,
181
+ 1 if data['slow_movement'] == 1 else 0,
182
+ 1 if data['tremor_severity'] > 5 else 0,
183
+ 1 if data['family_history'] == 1 else 0,
184
+ 1 if data['symptom_duration'] > 12 else 0
185
+ ])
186
 
187
+ prediction_proba = min(0.1 * risk_score, 0.95)
188
+ prediction_class = 1 if risk_score >= 4 else 0
189
 
190
+ if risk_score >= 5:
191
+ risk_level = "High Risk"
192
+ elif risk_score >= 3:
193
+ risk_level = "Moderate Risk"
194
+ else:
195
+ risk_level = "Low Risk"
196
+
197
+ # Calculate risk factors
198
+ risk_factors = calculate_risk_factors(data)
199
+
200
+ return {
201
+ "probability": float(prediction_proba),
202
+ "prediction": risk_level,
203
+ "parkinsons_prediction": prediction_class,
204
+ "using_model": using_trained_model, # Show whether we're using the trained model or mock
205
+ "risk_factors": risk_factors,
206
+ "execution_time_ms": int(random.uniform(50, 200)),
207
+ "model_version": "parkinsons-v1" if using_trained_model else "mock-model-v1"
208
+ }
209
+
210
+ def predict_parkinsons(gender, age, tremor, stiffness, balance_problems, slow_movement,
211
+ sleep_issues, tremor_severity, tremor_frequency, family_history,
212
+ symptom_duration):
213
+ # Simulate processing time
214
+ start_time = time.time()
215
+
216
+ # Format the input data
217
+ input_data = {
218
+ "gender": gender,
219
+ "age": age,
220
+ "tremor": 1 if tremor else 0,
221
+ "stiffness": 1 if stiffness else 0,
222
+ "balance_problems": 1 if balance_problems else 0,
223
+ "slow_movement": 1 if slow_movement else 0,
224
+ "sleep_issues": 1 if sleep_issues else 0,
225
+ "tremor_severity": tremor_severity,
226
+ "tremor_frequency": tremor_frequency,
227
+ "family_history": 1 if family_history else 0,
228
+ "symptom_duration": symptom_duration
229
+ }
230
+
231
+ # Process the data and get predictions
232
+ result = process_input_data(input_data)
233
+
234
+ # Update execution time
235
+ execution_time = (time.time() - start_time) * 1000
236
+ result["execution_time_ms"] = int(execution_time)
237
+
238
+ return result
239
+
240
+ def api_predict(
241
+ gender,
242
+ age,
243
+ tremor=0,
244
+ stiffness=0,
245
+ balance_problems=0,
246
+ slow_movement=0,
247
+ sleep_issues=0,
248
+ tremor_severity=0,
249
+ tremor_frequency="none",
250
+ family_history=0,
251
+ symptom_duration=0
252
+ ):
253
+ # Convert string values to appropriate types
254
+ if isinstance(tremor, str):
255
+ tremor = int(tremor)
256
+ if isinstance(stiffness, str):
257
+ stiffness = int(stiffness)
258
+ if isinstance(balance_problems, str):
259
+ balance_problems = int(balance_problems)
260
+ if isinstance(slow_movement, str):
261
+ slow_movement = int(slow_movement)
262
+ if isinstance(sleep_issues, str):
263
+ sleep_issues = int(sleep_issues)
264
+ if isinstance(family_history, str):
265
+ family_history = int(family_history)
266
+ if isinstance(age, str):
267
+ age = float(age)
268
+ if isinstance(tremor_severity, str):
269
+ tremor_severity = float(tremor_severity)
270
+ if isinstance(symptom_duration, str):
271
+ symptom_duration = float(symptom_duration)
272
+
273
+ result = predict_parkinsons(
274
+ gender,
275
+ age,
276
+ bool(tremor),
277
+ bool(stiffness),
278
+ bool(balance_problems),
279
+ bool(slow_movement),
280
+ bool(sleep_issues),
281
+ tremor_severity,
282
+ tremor_frequency,
283
+ bool(family_history),
284
+ symptom_duration
285
+ )
286
+
287
+ return result
288
+
289
+ # Create Gradio interface
290
+ with gr.Blocks(title="Parkinson's Disease Prediction") as demo:
291
+ gr.Markdown("# Parkinson's Disease Risk Prediction")
292
+ gr.Markdown("Fill in the details below to assess Parkinson's disease risk factors.")
293
+
294
+ with gr.Row():
295
+ with gr.Column():
296
+ gender = gr.Radio(["Male", "Female"], label="Gender")
297
+ age = gr.Slider(30, 95, value=65, label="Age")
298
+ tremor = gr.Checkbox(label="Resting Tremor")
299
+ stiffness = gr.Checkbox(label="Muscle Stiffness")
300
+ balance_problems = gr.Checkbox(label="Balance Problems")
301
+ slow_movement = gr.Checkbox(label="Slowness of Movement (Bradykinesia)")
302
+ sleep_issues = gr.Checkbox(label="Sleep Disturbances")
303
+ tremor_severity = gr.Slider(0, 10, value=0, label="Tremor Severity (0-10)")
304
+ tremor_frequency = gr.Dropdown(
305
+ ["none", "rare", "occasional", "frequent", "constant"],
306
+ label="Tremor Frequency",
307
+ value="none"
308
+ )
309
+ family_history = gr.Checkbox(label="Family History of Parkinson's")
310
+ symptom_duration = gr.Slider(0, 60, value=0, label="Symptom Duration (months)")
311
+
312
+ submit_btn = gr.Button("Predict Risk")
313
 
314
+ with gr.Column():
315
+ output = gr.JSON(label="Prediction Results")
316
+
317
+ with gr.Accordion("Model Info", open=True):
318
+ gr.Markdown(f"""
319
+ ## Model Information
320
+
321
+ - Model status: {"Using trained model" if using_trained_model else "Using fallback model"}
322
+ - Model type: {type(model).__name__}
323
+ """)
324
+
325
+ with gr.Accordion("API Information", open=False):
326
+ gr.Markdown("""
327
+ ## API Usage
328
+
329
+ This model can be accessed via API at `/api/predict` with the following parameters:
330
+
331
+ - `gender`: "Male" or "Female"
332
+ - `age`: Numerical age in years
333
+ - `tremor`: 0 or 1
334
+ - `stiffness`: 0 or 1
335
+ - `balance_problems`: 0 or 1
336
+ - `slow_movement`: 0 or 1
337
+ - `sleep_issues`: 0 or 1
338
+ - `tremor_severity`: 0-10
339
+ - `tremor_frequency`: "none", "rare", "occasional", "frequent", or "constant"
340
+ - `family_history`: 0 or 1
341
+ - `symptom_duration`: Duration in months
342
+ """)
343
+
344
+ submit_btn.click(
345
+ predict_parkinsons,
346
+ inputs=[
347
+ gender, age, tremor, stiffness, balance_problems, slow_movement,
348
+ sleep_issues, tremor_severity, tremor_frequency, family_history,
349
+ symptom_duration
350
+ ],
351
+ outputs=output
352
+ )
353
+
354
+ # Mount the API endpoint
355
+ demo.queue()
356
+ app = gr.mount_gradio_app(app=gr.routes.App(), blocks=demo, path="/")
357
+
358
+ # Create a FastAPI app
359
+ from fastapi import FastAPI
360
+ from fastapi.middleware.cors import CORSMiddleware
361
+
362
+ # Initialize FastAPI
363
+ fastapi_app = FastAPI(title="Parkinson's Disease Prediction API")
364
+
365
+ # Add CORS middleware
366
+ fastapi_app.add_middleware(
367
+ CORSMiddleware,
368
+ allow_origins=["*"],
369
+ allow_credentials=True,
370
+ allow_methods=["*"],
371
+ allow_headers=["*"],
372
+ )
373
+
374
+ # Define the request model
375
+ class PredictionRequest(BaseModel):
376
+ gender: str
377
+ age: float
378
+ tremor: int = 0
379
+ stiffness: int = 0
380
+ balance_problems: int = 0
381
+ slow_movement: int = 0
382
+ sleep_issues: int = 0
383
+ tremor_severity: float = 0
384
+ tremor_frequency: str = "none"
385
+ family_history: int = 0
386
+ symptom_duration: float = 0
387
+
388
+ # Define the response model
389
+ class PredictionResponse(BaseModel):
390
+ probability: float
391
+ prediction: str
392
+ parkinsons_prediction: int
393
+ using_model: bool
394
+ risk_factors: List[str]
395
+ execution_time_ms: int
396
+ model_version: str
397
+
398
+ @fastapi_app.get("/api/predict", response_model=PredictionResponse)
399
+ async def predict_get(
400
+ gender: str = Query(..., description="Gender ('Male' or 'Female')"),
401
+ age: float = Query(..., description="Age in years"),
402
+ tremor: int = Query(0, description="Presence of tremor (0 or 1)"),
403
+ stiffness: int = Query(0, description="Muscle stiffness (0 or 1)"),
404
+ balance_problems: int = Query(0, description="Balance problems (0 or 1)"),
405
+ slow_movement: int = Query(0, description="Slowness of movement (0 or 1)"),
406
+ sleep_issues: int = Query(0, description="Sleep disturbances (0 or 1)"),
407
+ tremor_severity: float = Query(0, description="Tremor severity (0-10)"),
408
+ tremor_frequency: str = Query("none", description="Tremor frequency"),
409
+ family_history: int = Query(0, description="Family history of Parkinson's (0 or 1)"),
410
+ symptom_duration: float = Query(0, description="Symptom duration in months")
411
+ ):
412
+ result = api_predict(
413
+ gender, age, tremor, stiffness, balance_problems, slow_movement,
414
+ sleep_issues, tremor_severity, tremor_frequency, family_history, symptom_duration
415
+ )
416
+ return result
417
+
418
+ @fastapi_app.post("/api/predict", response_model=PredictionResponse)
419
+ async def predict_post(request: PredictionRequest):
420
+ result = api_predict(
421
+ request.gender, request.age, request.tremor, request.stiffness,
422
+ request.balance_problems, request.slow_movement, request.sleep_issues,
423
+ request.tremor_severity, request.tremor_frequency, request.family_history,
424
+ request.symptom_duration
425
+ )
426
  return result
427
 
428
+ # Mount the FastAPI app
429
+ app.mount("/", fastapi_app)
 
430
 
 
431
  if __name__ == "__main__":
432
  import uvicorn
433
  uvicorn.run(app, host="0.0.0.0", port=7860)
model.joblib CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c15fdacbe8fc951161076e34f2d70b66cfa29a1f115351d211da32eb8eadc7d1
3
  size 18791
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9b339816fef395f170b7a359a41222f73461fcb352a7b84f05c7e096a0aafa55
3
  size 18791