diet_planner / app.py
rukia07's picture
initial commit
5bb7eae
from flask import Flask, render_template, request
import pandas as pd
import numpy as np
import plotly.graph_objects as go
app = Flask(__name__)
# Load the diet data
diet_df = pd.read_csv("edi-4data.csv")
# Diet category mapping
diet_category_map = {1: "underweight", 2: "normal", 3: "overweight", 4: "obese", 5: "extremely obese"}
# Replace missing values if any
diet_df.fillna(0, inplace=True)
def split_calorie_intake(total_calories):
breakfast_calories = total_calories * 0.3
lunch_calories = total_calories * 0.4
dinner_calories = total_calories * 0.3
return breakfast_calories, lunch_calories, dinner_calories
def generate_meal_options(df, calories):
meal_options = df.sample(frac=1).reset_index(drop=True)
total_calories = meal_options['Calories (kcal)'].sum()
while total_calories > calories + 200 or total_calories < calories - 200:
if total_calories > calories + 200:
meal_options = meal_options.iloc[:-1]
elif total_calories < calories - 200:
meal_options = pd.concat([meal_options, df.sample()])
total_calories = meal_options['Calories (kcal)'].sum()
return meal_options
def optimize_meal(meal_df, target_calories):
meal_df = meal_df.sort_values(by='Calories (kcal)', ascending=False)
selected_items = []
remaining_calories = target_calories
for index, row in meal_df.iterrows():
if remaining_calories >= row['Calories (kcal)']:
selected_items.append(index)
remaining_calories -= row['Calories (kcal)']
if remaining_calories > 0:
nearest_solution = None
nearest_difference = float('inf')
for index, row in meal_df.iterrows():
if index not in selected_items:
difference = abs(row['Calories (kcal)'] - remaining_calories)
if difference < nearest_difference:
nearest_solution = index
nearest_difference = difference
if nearest_solution is not None:
selected_items.append(nearest_solution)
return meal_df.loc[selected_items]
def generate_diet_chart(user_data, df):
temp_df = df.copy()
# Filter for vegetarian if needed
if user_data['dietary_preference'] == 'veg':
temp_df = temp_df[temp_df['veg/nonveg'] == 1]
# Remove foods with allergens/diseases mentioned
if user_data['allergies_diseases']:
allergies = user_data['allergies_diseases'].split(',')
for allergy in allergies:
temp_df = temp_df[~temp_df['Food Item'].str.contains(allergy.strip(), case=False, na=False)]
# Split the new calorie intake into meals
breakfast_calories, lunch_calories, dinner_calories = split_calorie_intake(user_data['new_calorie_intake'])
breakfast_options = generate_meal_options(temp_df, breakfast_calories)
lunch_options = generate_meal_options(temp_df, lunch_calories)
dinner_options = generate_meal_options(temp_df, dinner_calories)
breakfast_df = optimize_meal(breakfast_options, breakfast_calories)
lunch_df = optimize_meal(lunch_options, lunch_calories)
dinner_df = optimize_meal(dinner_options, dinner_calories)
return breakfast_df, lunch_df, dinner_df
@app.route("/", methods=["GET", "POST"])
def index():
results = None
if request.method == "POST":
# Get user input from the form
user_gender = request.form.get("user_gender")
user_gender_value = 0 if user_gender == "Male" else 1
user_height = float(request.form.get("user_height"))
user_weight = float(request.form.get("user_weight"))
user_age = int(request.form.get("user_age"))
allergies_diseases = request.form.get("allergies_diseases", "").strip().lower()
dietary_preference = request.form.get("dietary_preference", "").strip().lower()
activity_level = int(request.form.get("activity_level"))
# Calculate BMI
bmi = user_weight / ((user_height / 100) ** 2)
# Dummy prediction for BMI category
if bmi < 18.5:
predicted_category = 1 # Underweight
elif bmi < 25:
predicted_category = 2 # Normal weight
elif bmi < 30:
predicted_category = 3 # Overweight
elif bmi < 35:
predicted_category = 4 # Obese
else:
predicted_category = 5 # Extremely Obese
# Calculate initial calorie intake using the Mifflin-St Jeor equation
initial_calorie_intake = 10 * user_weight + 6.25 * user_height - 5 * user_age + (5 if user_gender_value == 0 else -161)
# Adjust calorie intake based on BMI category
if predicted_category == 1: # Underweight
normal_bmi_calories = 18 * ((user_height / 100) ** 2)
new_calorie_intake = initial_calorie_intake + normal_bmi_calories + 650
calorie_adjustment = normal_bmi_calories
elif predicted_category in [3, 4]: # Overweight or Obese
normal_bmi_calories = 25 * ((user_height / 100) ** 2)
new_calorie_intake = initial_calorie_intake - normal_bmi_calories + 200
calorie_adjustment = normal_bmi_calories
else:
calorie_adjustment = 0
new_calorie_intake = initial_calorie_intake + calorie_adjustment + 350
user_data = {
'bmi': round(bmi, 2),
'body_category': diet_category_map[predicted_category],
'initial_calorie_intake': round(initial_calorie_intake, 2),
'calorie_adjustment': calorie_adjustment,
'new_calorie_intake': round(new_calorie_intake, 2),
'allergies_diseases': allergies_diseases,
'dietary_preference': dietary_preference,
'activity_level': activity_level,
'age': user_age
}
# Generate diet chart for breakfast, lunch, and dinner
breakfast_df, lunch_df, dinner_df = generate_diet_chart(user_data, diet_df)
# Generate Plotly chart for calorie distribution among meals
meal_labels = ['Breakfast', 'Lunch', 'Dinner']
calorie_values = [
breakfast_df['Calories (kcal)'].sum(),
lunch_df['Calories (kcal)'].sum(),
dinner_df['Calories (kcal)'].sum()
]
fig_cal = go.Figure(data=[go.Bar(x=meal_labels, y=calorie_values, marker_color=['blue', 'green', 'orange'])])
fig_cal.update_layout(title_text='Calorie Distribution Among Meals',
xaxis_title='Meal', yaxis_title='Calories (kcal)')
calorie_chart = fig_cal.to_html(full_html=False)
# Generate Plotly chart for nutrient distribution across meals
nutrient_labels = ['Protein', 'Carbohydrates', 'Fats']
breakfast_nutrients = [
breakfast_df['Protein (g)'].sum(),
breakfast_df['Carbohydrates(g)'].sum(),
breakfast_df['Fats (g)'].sum()
]
lunch_nutrients = [
lunch_df['Protein (g)'].sum(),
lunch_df['Carbohydrates(g)'].sum(),
lunch_df['Fats (g)'].sum()
]
dinner_nutrients = [
dinner_df['Protein (g)'].sum(),
dinner_df['Carbohydrates(g)'].sum(),
dinner_df['Fats (g)'].sum()
]
fig_nutrient = go.Figure(data=[
go.Bar(name='Breakfast', x=nutrient_labels, y=breakfast_nutrients),
go.Bar(name='Lunch', x=nutrient_labels, y=lunch_nutrients),
go.Bar(name='Dinner', x=nutrient_labels, y=dinner_nutrients)
])
fig_nutrient.update_layout(barmode='group', title='Nutrient Distribution Across Meals',
xaxis_title='Nutrients', yaxis_title='Quantity (g)')
nutrient_chart = fig_nutrient.to_html(full_html=False)
# Convert dataframes to dictionary records for easy templating
breakfast_records = breakfast_df.to_dict(orient='records')
lunch_records = lunch_df.to_dict(orient='records')
dinner_records = dinner_df.to_dict(orient='records')
results = {
'bmi': round(bmi, 2),
'body_category': diet_category_map[predicted_category],
'initial_calorie_intake': round(initial_calorie_intake, 2),
'new_calorie_intake': round(new_calorie_intake, 2),
'age': user_age,
'breakfast': breakfast_records,
'breakfast_total_calories': breakfast_df['Calories (kcal)'].sum(),
'breakfast_total_protein': breakfast_df['Protein (g)'].sum(),
'breakfast_total_carbs': breakfast_df['Carbohydrates(g)'].sum(),
'breakfast_total_fats': breakfast_df['Fats (g)'].sum(),
'lunch': lunch_records,
'lunch_total_calories': lunch_df['Calories (kcal)'].sum(),
'lunch_total_protein': lunch_df['Protein (g)'].sum(),
'lunch_total_carbs': lunch_df['Carbohydrates(g)'].sum(),
'lunch_total_fats': lunch_df['Fats (g)'].sum(),
'dinner': dinner_records,
'dinner_total_calories': dinner_df['Calories (kcal)'].sum(),
'dinner_total_protein': dinner_df['Protein (g)'].sum(),
'dinner_total_carbs': dinner_df['Carbohydrates(g)'].sum(),
'dinner_total_fats': dinner_df['Fats (g)'].sum(),
'calorie_chart': calorie_chart,
'nutrient_chart': nutrient_chart
}
return render_template("index.html", results=results)
if __name__ == '__main__':
app.run(debug=True,port=5265)