Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import pandas as pd
|
3 |
+
import gradio as gr
|
4 |
+
import matplotlib.pyplot as plt
|
5 |
+
import seaborn as sns
|
6 |
+
from typing import Dict, List, Tuple
|
7 |
+
|
8 |
+
class HealthStandards:
|
9 |
+
"""Simplified health standards with error handling"""
|
10 |
+
|
11 |
+
@staticmethod
|
12 |
+
def get_bmi_status(bmi: float) -> Dict:
|
13 |
+
try:
|
14 |
+
if bmi < 18.5:
|
15 |
+
return {"status": "Underweight", "risk": "High",
|
16 |
+
"recommendation": "Consult nutritionist for weight gain plan"}
|
17 |
+
elif bmi < 24.9:
|
18 |
+
return {"status": "Normal", "risk": "Low",
|
19 |
+
"recommendation": "Maintain healthy lifestyle"}
|
20 |
+
elif bmi < 29.9:
|
21 |
+
return {"status": "Overweight", "risk": "Moderate",
|
22 |
+
"recommendation": "Consider diet and exercise plan"}
|
23 |
+
else:
|
24 |
+
return {"status": "Obese", "risk": "High",
|
25 |
+
"recommendation": "Seek medical guidance"}
|
26 |
+
except Exception as e:
|
27 |
+
return {"status": "Error", "risk": "Unknown",
|
28 |
+
"recommendation": f"Error processing BMI: {str(e)}"}
|
29 |
+
|
30 |
+
@staticmethod
|
31 |
+
def get_bp_status(bp: float) -> Dict:
|
32 |
+
try:
|
33 |
+
if bp < 120:
|
34 |
+
return {"status": "Normal", "risk": "Low",
|
35 |
+
"recommendation": "Maintain healthy lifestyle"}
|
36 |
+
elif bp < 130:
|
37 |
+
return {"status": "Elevated", "risk": "Moderate",
|
38 |
+
"recommendation": "Monitor regularly"}
|
39 |
+
elif bp < 140:
|
40 |
+
return {"status": "Stage 1 Hypertension", "risk": "High",
|
41 |
+
"recommendation": "Consult healthcare provider"}
|
42 |
+
else:
|
43 |
+
return {"status": "Stage 2 Hypertension", "risk": "Very High",
|
44 |
+
"recommendation": "Immediate medical attention needed"}
|
45 |
+
except Exception as e:
|
46 |
+
return {"status": "Error", "risk": "Unknown",
|
47 |
+
"recommendation": f"Error processing blood pressure: {str(e)}"}
|
48 |
+
|
49 |
+
@staticmethod
|
50 |
+
def get_glucose_status(glucose: float) -> Dict:
|
51 |
+
try:
|
52 |
+
if glucose < 100:
|
53 |
+
return {"status": "Normal", "risk": "Low",
|
54 |
+
"recommendation": "Maintain healthy diet"}
|
55 |
+
elif glucose < 125:
|
56 |
+
return {"status": "Prediabetes", "risk": "Moderate",
|
57 |
+
"recommendation": "Lifestyle modifications needed"}
|
58 |
+
else:
|
59 |
+
return {"status": "Diabetes Range", "risk": "High",
|
60 |
+
"recommendation": "Consult healthcare provider"}
|
61 |
+
except Exception as e:
|
62 |
+
return {"status": "Error", "risk": "Unknown",
|
63 |
+
"recommendation": f"Error processing glucose: {str(e)}"}
|
64 |
+
|
65 |
+
class HealthAnalyzer:
|
66 |
+
"""Analyzes health metrics with error handling"""
|
67 |
+
|
68 |
+
def __init__(self):
|
69 |
+
self.standards = HealthStandards()
|
70 |
+
|
71 |
+
def analyze_metrics(self, age: float, bmi: float, bp: float,
|
72 |
+
glucose: float) -> Tuple[Dict, str]:
|
73 |
+
try:
|
74 |
+
# Get individual assessments
|
75 |
+
bmi_assessment = self.standards.get_bmi_status(bmi)
|
76 |
+
bp_assessment = self.standards.get_bp_status(bp)
|
77 |
+
glucose_assessment = self.standards.get_glucose_status(glucose)
|
78 |
+
|
79 |
+
# Calculate risk score
|
80 |
+
risk_factors = 0
|
81 |
+
if bmi_assessment["risk"] in ["High", "Very High"]: risk_factors += 1
|
82 |
+
if bp_assessment["risk"] in ["High", "Very High"]: risk_factors += 1
|
83 |
+
if glucose_assessment["risk"] in ["High", "Very High"]: risk_factors += 1
|
84 |
+
if age > 60: risk_factors += 1
|
85 |
+
|
86 |
+
risk_score = (risk_factors / 4) * 100
|
87 |
+
|
88 |
+
analysis = {
|
89 |
+
"metrics": {
|
90 |
+
"BMI": bmi_assessment,
|
91 |
+
"Blood Pressure": bp_assessment,
|
92 |
+
"Glucose": glucose_assessment
|
93 |
+
},
|
94 |
+
"risk_score": risk_score
|
95 |
+
}
|
96 |
+
|
97 |
+
# Generate report
|
98 |
+
report = self.generate_report(analysis, age)
|
99 |
+
|
100 |
+
return analysis, report
|
101 |
+
|
102 |
+
except Exception as e:
|
103 |
+
return {"error": str(e)}, "Error occurred during analysis"
|
104 |
+
|
105 |
+
def generate_report(self, analysis: Dict, age: float) -> str:
|
106 |
+
try:
|
107 |
+
report = [
|
108 |
+
"=== HEALTH ANALYSIS REPORT ===\n",
|
109 |
+
f"Overall Risk Score: {analysis['risk_score']:.1f}%\n",
|
110 |
+
f"Risk Level: {self.get_risk_level(analysis['risk_score'])}\n",
|
111 |
+
"\nDetailed Analysis:"
|
112 |
+
]
|
113 |
+
|
114 |
+
for metric, assessment in analysis["metrics"].items():
|
115 |
+
report.extend([
|
116 |
+
f"\n{metric}:",
|
117 |
+
f"Status: {assessment['status']}",
|
118 |
+
f"Risk Level: {assessment['risk']}",
|
119 |
+
f"Recommendation: {assessment['recommendation']}"
|
120 |
+
])
|
121 |
+
|
122 |
+
return "\n".join(report)
|
123 |
+
|
124 |
+
except Exception as e:
|
125 |
+
return f"Error generating report: {str(e)}"
|
126 |
+
|
127 |
+
@staticmethod
|
128 |
+
def get_risk_level(risk_score: float) -> str:
|
129 |
+
if risk_score < 33:
|
130 |
+
return "Low"
|
131 |
+
elif risk_score < 66:
|
132 |
+
return "Moderate"
|
133 |
+
else:
|
134 |
+
return "High"
|
135 |
+
|
136 |
+
def create_visualization(analysis: Dict) -> plt.Figure:
|
137 |
+
"""Create visualization with error handling"""
|
138 |
+
try:
|
139 |
+
sns.set_style("whitegrid") # Use seaborn style directly
|
140 |
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
|
141 |
+
|
142 |
+
# Metrics comparison
|
143 |
+
metrics = list(analysis["metrics"].keys())
|
144 |
+
risk_levels = [assessment["risk"] for assessment in analysis["metrics"].values()]
|
145 |
+
risk_values = [{"Low": 1, "Moderate": 2, "High": 3, "Very High": 4}.get(r, 0)
|
146 |
+
for r in risk_levels]
|
147 |
+
|
148 |
+
colors = ['green' if r == "Low" else 'yellow' if r == "Moderate"
|
149 |
+
else 'red' for r in risk_levels]
|
150 |
+
|
151 |
+
ax1.bar(metrics, risk_values, color=colors)
|
152 |
+
ax1.set_title("Health Metrics Risk Levels")
|
153 |
+
ax1.set_ylim(0, 4)
|
154 |
+
ax1.set_yticks([1, 2, 3, 4])
|
155 |
+
ax1.set_yticklabels(['Low', 'Moderate', 'High', 'Very High'])
|
156 |
+
|
157 |
+
# Risk gauge
|
158 |
+
risk_score = analysis["risk_score"]
|
159 |
+
colors = ['green', 'yellow', 'red']
|
160 |
+
ax2.pie([risk_score, 100-risk_score],
|
161 |
+
colors=[colors[int(risk_score/33.34)], 'lightgray'],
|
162 |
+
startangle=90, counterclock=False)
|
163 |
+
ax2.set_title(f"Overall Risk Score: {risk_score:.1f}%")
|
164 |
+
|
165 |
+
plt.tight_layout()
|
166 |
+
return fig
|
167 |
+
|
168 |
+
except Exception as e:
|
169 |
+
# Create error figure
|
170 |
+
fig, ax = plt.subplots(figsize=(8, 4))
|
171 |
+
ax.text(0.5, 0.5, f"Error creating visualization: {str(e)}",
|
172 |
+
ha='center', va='center')
|
173 |
+
ax.axis('off')
|
174 |
+
return fig
|
175 |
+
|
176 |
+
def analyze_health(age: float, bmi: float, bp: float, glucose: float) -> Tuple[plt.Figure, str]:
|
177 |
+
"""Main analysis function with error handling"""
|
178 |
+
try:
|
179 |
+
analyzer = HealthAnalyzer()
|
180 |
+
analysis, report = analyzer.analyze_metrics(age, bmi, bp, glucose)
|
181 |
+
|
182 |
+
if "error" in analysis:
|
183 |
+
raise Exception(analysis["error"])
|
184 |
+
|
185 |
+
fig = create_visualization(analysis)
|
186 |
+
return fig, report
|
187 |
+
|
188 |
+
except Exception as e:
|
189 |
+
error_fig, ax = plt.subplots(figsize=(8, 4))
|
190 |
+
ax.text(0.5, 0.5, f"Error: {str(e)}", ha='center', va='center')
|
191 |
+
ax.axis('off')
|
192 |
+
return error_fig, f"An error occurred: {str(e)}"
|
193 |
+
|
194 |
+
# Create Gradio interface
|
195 |
+
def create_gradio_interface():
|
196 |
+
interface = gr.Interface(
|
197 |
+
fn=analyze_health,
|
198 |
+
inputs=[
|
199 |
+
gr.Slider(20, 90, value=50, label="Age"),
|
200 |
+
gr.Slider(15, 45, value=25, label="BMI"),
|
201 |
+
gr.Slider(80, 200, value=120, label="Blood Pressure"),
|
202 |
+
gr.Slider(70, 200, value=100, label="Glucose")
|
203 |
+
],
|
204 |
+
outputs=[
|
205 |
+
gr.Plot(label="Health Analysis Dashboard"),
|
206 |
+
gr.Textbox(label="Health Report", lines=10)
|
207 |
+
],
|
208 |
+
title="Health Analysis System",
|
209 |
+
description="Enter patient metrics for health analysis."
|
210 |
+
)
|
211 |
+
return interface
|
212 |
+
|
213 |
+
if __name__ == "__main__":
|
214 |
+
# Launch the Gradio interface
|
215 |
+
interface = create_gradio_interface()
|
216 |
+
interface.launch()
|