early-prediction-for-ml_proj / health_score.py
mohitrajdeo
feat: add health score assessment module
a1a5f27
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Initialize session state variables if they don't exist
def init_session_state():
if 'current_step' not in st.session_state:
st.session_state.current_step = 0
if 'assessment_data' not in st.session_state:
st.session_state.assessment_data = {}
if 'results_calculated' not in st.session_state:
st.session_state.results_calculated = False
if 'risk_data' not in st.session_state:
st.session_state.risk_data = []
if 'health_score' not in st.session_state:
st.session_state.health_score = 0
if 'recommendations' not in st.session_state:
st.session_state.recommendations = []
# Define steps for the assessment
steps = [
{"title": "Basic Information", "fields": ["age", "gender", "height", "weight"]},
{"title": "Lifestyle", "fields": ["smoking_status", "alcohol_consumption", "physical_activity", "diet_type"]},
{"title": "Medical History", "fields": ["family_history_diabetes", "family_history_heart_disease",
"family_history_hypertension", "previous_diagnoses"]},
{"title": "Vital Signs", "fields": ["systolic_bp", "diastolic_bp", "resting_heart_rate"]},
{"title": "Mental Health", "fields": ["stress_level", "sleep_quality", "sleep_duration"]},
{"title": "Nutrition", "fields": ["daily_water_intake", "daily_fruit_veg_servings"]},
{"title": "Additional Metrics", "fields": ["waist_circumference", "body_fat_percentage"]},
{"title": "Additional Health Information", "fields": ["family_history_asthma", "family_history_obesity",
"family_history_depression", "allergies",
"chronic_pain", "mental_health_history"]}
]
# Function to calculate risk for different diseases
def calculate_risk(disease, data):
risk = 0
if disease == "Diabetes":
if data.get("age", 0) > 45: risk += 10
if float(data.get("bmi", 0)) > 30: risk += 15
if data.get("family_history_diabetes", False): risk += 15
if data.get("physical_activity", "") == "sedentary": risk += 10
elif disease == "Heart Disease":
if data.get("age", 0) > 55: risk += 10
if data.get("systolic_bp", 0) > 140 or data.get("diastolic_bp", 0) > 90: risk += 15
if data.get("family_history_heart_disease", False): risk += 15
if data.get("smoking_status", "") == "current": risk += 15
elif disease == "Hypertension":
if data.get("systolic_bp", 0) > 140 or data.get("diastolic_bp", 0) > 90: risk += 20
if data.get("family_history_hypertension", False): risk += 15
if data.get("alcohol_consumption", "") == "heavy": risk += 10
elif disease == "Obesity":
if float(data.get("bmi", 0)) > 30: risk += 30
if data.get("physical_activity", "") == "sedentary": risk += 15
if data.get("family_history_obesity", False): risk += 10
elif disease == "Asthma":
if data.get("family_history_asthma", False): risk += 20
if data.get("smoking_status", "") == "current": risk += 15
allergies = data.get("allergies", "").lower()
if "pollen" in allergies or "dust" in allergies: risk += 10
elif disease == "Depression":
if data.get("family_history_depression", False): risk += 15
if data.get("stress_level", 0) > 7: risk += 15
if data.get("sleep_quality", "") == "poor": risk += 10
mental_health = data.get("mental_health_history", "").lower()
if "depression" in mental_health or "anxiety" in mental_health: risk += 20
return min(risk, 100)
# Function to generate recommendations
def generate_recommendations(data):
recommendations = []
if data.get("physical_activity", "") in ["sedentary", "light"]:
recommendations.append("Increase your daily physical activity to at least 30 minutes of moderate exercise.")
if data.get("daily_fruit_veg_servings", 0) < 5:
recommendations.append("Increase your daily intake of fruits and vegetables to at least 5 servings.")
if data.get("daily_water_intake", 0) < 2000:
recommendations.append("Increase your daily water intake to at least 2 liters (2000ml).")
if data.get("sleep_duration", 0) < 7 or data.get("sleep_quality", "") in ["poor", "fair"]:
recommendations.append("Aim for 7-9 hours of quality sleep per night to improve overall health.")
if data.get("stress_level", 0) > 7:
recommendations.append("Practice stress-reduction techniques such as meditation or deep breathing exercises.")
if data.get("smoking_status", "") == "current":
recommendations.append("Consider quitting smoking to significantly reduce your risk of heart disease and other health problems.")
if data.get("alcohol_consumption", "") == "heavy":
recommendations.append("Reduce alcohol consumption to moderate levels or consider abstaining completely.")
if float(data.get("bmi", 0)) > 25:
recommendations.append("Work on maintaining a healthy weight through a balanced diet and regular exercise.")
if data.get("chronic_pain", "") != "none":
recommendations.append("Consult with a healthcare professional about managing your chronic pain and consider physical therapy or pain management techniques.")
if data.get("mental_health_history", "") != "":
recommendations.append("Continue to prioritize your mental health. Consider regular check-ins with a mental health professional.")
return recommendations
# Function to calculate results
def calculate_results():
# Calculate BMI if not already done
if "bmi" not in st.session_state.assessment_data:
height_m = st.session_state.assessment_data.get("height", 170) / 100
weight = st.session_state.assessment_data.get("weight", 70)
bmi = weight / (height_m * height_m)
st.session_state.assessment_data["bmi"] = round(bmi, 1)
# Calculate risk for each disease
diseases = ["Diabetes", "Heart Disease", "Hypertension", "Obesity", "Asthma", "Depression"]
risk_data = []
for disease in diseases:
risk = calculate_risk(disease, st.session_state.assessment_data)
risk_data.append({"disease": disease, "risk": risk})
st.session_state.risk_data = risk_data
# Calculate overall health score (scaled to 0-100)
total_risk = sum(item["risk"] for item in risk_data)
health_score = round(100 * (1 - total_risk / (len(diseases) * 100)))
st.session_state.health_score = health_score
# Generate recommendations
st.session_state.recommendations = generate_recommendations(st.session_state.assessment_data)
st.session_state.results_calculated = True
# Function to handle form submission for each step
def process_step(step_index):
# Save form data to session state
for field in steps[step_index]["fields"]:
if field in st.session_state:
st.session_state.assessment_data[field] = st.session_state[field]
# Move to next step or calculate results
if step_index < len(steps) - 1:
st.session_state.current_step += 1
else:
calculate_results()
# Function to go back to previous step
def go_back():
if st.session_state.current_step > 0:
st.session_state.current_step -= 1
# Function to restart assessment
def restart_assessment():
st.session_state.current_step = 0
st.session_state.assessment_data = {}
st.session_state.results_calculated = False
st.session_state.risk_data = []
st.session_state.health_score = 0
st.session_state.recommendations = []
# Main function for the Health Score module
def show_health_score():
st.title("🏥 Health Score Assessment")
# Initialize session state
init_session_state()
# Display results if calculated
if st.session_state.results_calculated:
st.header("Your Health Assessment Results")
# Create columns for layout
col1, col2 = st.columns(2)
with col1:
# Bar chart for disease risks
risk_df = pd.DataFrame(st.session_state.risk_data)
fig = px.bar(
risk_df,
x='disease',
y='risk',
title='Disease Risk Assessment',
labels={'disease': 'Disease', 'risk': 'Risk Score'},
color='risk',
color_continuous_scale=[(0, 'green'), (0.5, 'yellow'), (1, 'red')]
)
st.plotly_chart(fig, use_container_width=True)
with col2:
# Radar chart for disease risks
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=[item["risk"] for item in st.session_state.risk_data],
theta=[item["disease"] for item in st.session_state.risk_data],
fill='toself',
name='Risk Profile'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 100]
)
),
title="Health Risk Radar"
)
st.plotly_chart(fig, use_container_width=True)
# Health score gauge
fig = go.Figure(go.Indicator(
mode="gauge+number",
value=st.session_state.health_score,
domain={'x': [0, 1], 'y': [0, 1]},
title={'text': "Overall Health Score"},
gauge={
'axis': {'range': [0, 100]},
'bar': {'color': "darkblue"},
'steps': [
{'range': [0, 30], 'color': "red"},
{'range': [30, 70], 'color': "yellow"},
{'range': [70, 100], 'color': "green"}
]
}
))
st.plotly_chart(fig, use_container_width=True)
# Recommendations
st.subheader("Recommendations")
for i, recommendation in enumerate(st.session_state.recommendations):
st.markdown(f"- {recommendation}")
# Button to restart assessment
if st.button("Retake Assessment"):
restart_assessment()
# Display assessment form if results not calculated
else:
current_step = st.session_state.current_step
step = steps[current_step]
st.header(f"Comprehensive Health Assessment")
st.subheader(f"{step['title']} (Step {current_step + 1} of {len(steps)})")
# Create a centered container with smaller width
col1, form_col, col3 = st.columns([1, 2, 1])
with form_col:
with st.form(f"step_{current_step}_form"):
# Basic Information
if "age" in step["fields"]:
st.session_state.age = st.number_input("Age", 0, 120, st.session_state.assessment_data.get("age", 30))
if "gender" in step["fields"]:
st.session_state.gender = st.selectbox("Gender",
["male", "female", "other"],
["male", "female", "other"].index(st.session_state.assessment_data.get("gender", "male")))
if "height" in step["fields"]:
st.session_state.height = st.number_input("Height (cm)", 100, 250, st.session_state.assessment_data.get("height", 170))
if "weight" in step["fields"]:
st.session_state.weight = st.number_input("Weight (kg)", 30, 300, st.session_state.assessment_data.get("weight", 70))
# Lifestyle
if "smoking_status" in step["fields"]:
st.session_state.smoking_status = st.selectbox("Smoking Status",
["never", "former", "current"],
["never", "former", "current"].index(st.session_state.assessment_data.get("smoking_status", "never")))
if "alcohol_consumption" in step["fields"]:
st.session_state.alcohol_consumption = st.selectbox("Alcohol Consumption",
["none", "moderate", "heavy"],
["none", "moderate", "heavy"].index(st.session_state.assessment_data.get("alcohol_consumption", "moderate")))
if "physical_activity" in step["fields"]:
st.session_state.physical_activity = st.selectbox("Physical Activity Level",
["sedentary", "light", "moderate", "vigorous"],
["sedentary", "light", "moderate", "vigorous"].index(st.session_state.assessment_data.get("physical_activity", "moderate")))
if "diet_type" in step["fields"]:
st.session_state.diet_type = st.selectbox("Diet Type",
["balanced", "high-carb", "high-protein", "vegetarian", "vegan"],
["balanced", "high-carb", "high-protein", "vegetarian", "vegan"].index(st.session_state.assessment_data.get("diet_type", "balanced")))
# Medical History
if "family_history_diabetes" in step["fields"]:
st.session_state.family_history_diabetes = st.checkbox("Family History of Diabetes", st.session_state.assessment_data.get("family_history_diabetes", False))
if "family_history_heart_disease" in step["fields"]:
st.session_state.family_history_heart_disease = st.checkbox("Family History of Heart Disease", st.session_state.assessment_data.get("family_history_heart_disease", False))
if "family_history_hypertension" in step["fields"]:
st.session_state.family_history_hypertension = st.checkbox("Family History of Hypertension", st.session_state.assessment_data.get("family_history_hypertension", False))
if "previous_diagnoses" in step["fields"]:
st.session_state.previous_diagnoses = st.text_input("Previous Diagnoses (comma separated)", st.session_state.assessment_data.get("previous_diagnoses", ""))
# Vital Signs
if "systolic_bp" in step["fields"]:
st.session_state.systolic_bp = st.number_input("Systolic Blood Pressure", 70, 220, st.session_state.assessment_data.get("systolic_bp", 120))
if "diastolic_bp" in step["fields"]:
st.session_state.diastolic_bp = st.number_input("Diastolic Blood Pressure", 40, 130, st.session_state.assessment_data.get("diastolic_bp", 80))
if "resting_heart_rate" in step["fields"]:
st.session_state.resting_heart_rate = st.number_input("Resting Heart Rate", 40, 120, st.session_state.assessment_data.get("resting_heart_rate", 70))
# Mental Health
if "stress_level" in step["fields"]:
st.session_state.stress_level = st.slider("Stress Level (1-10)", 1, 10, st.session_state.assessment_data.get("stress_level", 5))
if "sleep_quality" in step["fields"]:
st.session_state.sleep_quality = st.selectbox("Sleep Quality",
["poor", "fair", "good", "excellent"],
["poor", "fair", "good", "excellent"].index(st.session_state.assessment_data.get("sleep_quality", "good")))
if "sleep_duration" in step["fields"]:
st.session_state.sleep_duration = st.number_input("Sleep Duration (hours)", 3.0, 12.0, float(st.session_state.assessment_data.get("sleep_duration", 7.0)), 0.5)
# Nutrition
if "daily_water_intake" in step["fields"]:
st.session_state.daily_water_intake = st.number_input("Daily Water Intake (ml)", 0, 5000, st.session_state.assessment_data.get("daily_water_intake", 2000), 100)
if "daily_fruit_veg_servings" in step["fields"]:
st.session_state.daily_fruit_veg_servings = st.number_input("Daily Fruit & Vegetable Servings", 0, 10, st.session_state.assessment_data.get("daily_fruit_veg_servings", 3))
# Additional Metrics
if "waist_circumference" in step["fields"]:
st.session_state.waist_circumference = st.number_input("Waist Circumference (cm)", 50, 200, st.session_state.assessment_data.get("waist_circumference", 80))
if "body_fat_percentage" in step["fields"]:
st.session_state.body_fat_percentage = st.number_input("Body Fat Percentage", 5.0, 50.0, float(st.session_state.assessment_data.get("body_fat_percentage", 20.0)), 0.5)
# Additional Health Information
if "family_history_asthma" in step["fields"]:
st.session_state.family_history_asthma = st.checkbox("Family History of Asthma", st.session_state.assessment_data.get("family_history_asthma", False))
if "family_history_obesity" in step["fields"]:
st.session_state.family_history_obesity = st.checkbox("Family History of Obesity", st.session_state.assessment_data.get("family_history_obesity", False))
if "family_history_depression" in step["fields"]:
st.session_state.family_history_depression = st.checkbox("Family History of Depression", st.session_state.assessment_data.get("family_history_depression", False))
if "allergies" in step["fields"]:
st.session_state.allergies = st.text_input("Allergies (comma separated)", st.session_state.assessment_data.get("allergies", ""))
if "chronic_pain" in step["fields"]:
st.session_state.chronic_pain = st.selectbox("Chronic Pain Level",
["none", "mild", "moderate", "severe"],
["none", "mild", "moderate", "severe"].index(st.session_state.assessment_data.get("chronic_pain", "none")))
if "mental_health_history" in step["fields"]:
st.session_state.mental_health_history = st.text_area("Mental Health History", st.session_state.assessment_data.get("mental_health_history", ""))
# Form buttons
col1, col2 = st.columns(2)
with col1:
if current_step > 0:
back_button = st.form_submit_button("Back")
if back_button:
go_back()
with col2:
if current_step < len(steps) - 1:
next_button = st.form_submit_button("Next")
if next_button:
process_step(current_step)
else:
submit_button = st.form_submit_button("Submit Assessment")
if submit_button:
process_step(current_step)