|
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 |
|
|
|
|
|
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 = [] |
|
|
|
|
|
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"]} |
|
] |
|
|
|
|
|
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) |
|
|
|
|
|
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 |
|
|
|
|
|
def calculate_results(): |
|
|
|
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) |
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
st.session_state.recommendations = generate_recommendations(st.session_state.assessment_data) |
|
|
|
st.session_state.results_calculated = True |
|
|
|
|
|
def process_step(step_index): |
|
|
|
for field in steps[step_index]["fields"]: |
|
if field in st.session_state: |
|
st.session_state.assessment_data[field] = st.session_state[field] |
|
|
|
|
|
if step_index < len(steps) - 1: |
|
st.session_state.current_step += 1 |
|
else: |
|
calculate_results() |
|
|
|
|
|
def go_back(): |
|
if st.session_state.current_step > 0: |
|
st.session_state.current_step -= 1 |
|
|
|
|
|
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 = [] |
|
|
|
|
|
def show_health_score(): |
|
st.title("🏥 Health Score Assessment") |
|
|
|
|
|
init_session_state() |
|
|
|
|
|
if st.session_state.results_calculated: |
|
st.header("Your Health Assessment Results") |
|
|
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
|
|
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: |
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
st.subheader("Recommendations") |
|
for i, recommendation in enumerate(st.session_state.recommendations): |
|
st.markdown(f"- {recommendation}") |
|
|
|
|
|
if st.button("Retake Assessment"): |
|
restart_assessment() |
|
|
|
|
|
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)})") |
|
|
|
|
|
col1, form_col, col3 = st.columns([1, 2, 1]) |
|
|
|
with form_col: |
|
with st.form(f"step_{current_step}_form"): |
|
|
|
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)) |
|
|
|
|
|
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"))) |
|
|
|
|
|
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", "")) |
|
|
|
|
|
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)) |
|
|
|
|
|
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) |
|
|
|
|
|
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)) |
|
|
|
|
|
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) |
|
|
|
|
|
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", "")) |
|
|
|
|
|
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) |