File size: 12,975 Bytes
6926480
 
 
 
 
 
93a433f
6926480
 
93a433f
6926480
 
 
93a433f
6926480
93a433f
6926480
93a433f
 
6926480
 
 
 
93a433f
6926480
 
 
 
 
 
93a433f
6926480
93a433f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6926480
 
 
93a433f
 
 
 
 
 
 
 
6926480
93a433f
 
6926480
 
 
 
93a433f
 
6926480
 
93a433f
6926480
 
 
93a433f
 
 
 
6926480
93a433f
 
 
6926480
93a433f
 
 
 
 
 
6926480
93a433f
6926480
 
 
93a433f
6926480
93a433f
6926480
 
 
93a433f
 
6926480
 
93a433f
6926480
93a433f
6926480
93a433f
 
 
 
6926480
 
 
93a433f
6926480
93a433f
 
6926480
 
93a433f
6926480
 
 
 
 
 
 
 
 
93a433f
 
6926480
 
 
 
 
 
 
 
 
93a433f
6926480
93a433f
 
6926480
 
93a433f
6926480
93a433f
 
6926480
 
 
 
 
 
93a433f
 
6926480
93a433f
 
6926480
93a433f
6926480
 
93a433f
 
6926480
 
 
 
93a433f
 
 
 
 
 
 
 
 
 
 
 
 
6926480
93a433f
 
 
 
 
 
 
 
 
6926480
 
93a433f
6926480
 
 
 
93a433f
 
 
6926480
93a433f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6926480
93a433f
 
 
 
 
 
 
 
 
 
6926480
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
import gradio as gr
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from datasets import load_dataset
import warnings
import matplotlib.pyplot as plt
warnings.filterwarnings('ignore')

# Load the Indian food dataset or use fallback data
try:
    ds = load_dataset("Anupam007/nutarian-Indianfood")
    food_df = pd.DataFrame(ds['train'])
    print(f"Successfully loaded dataset with {len(food_df)} items")
    
    # Clean and prepare dataset
    required_columns = ['name', 'calories', 'protein', 'carbohydrates', 'fat']
    column_mapping = {'Name': 'name', 'Calories': 'calories', 'Protein': 'protein', 
                      'Carbs': 'carbohydrates', 'Fats': 'fat', 'Category': 'food_group'}
    for old_col, new_col in column_mapping.items():
        if old_col in food_df.columns:
            food_df = food_df.rename(columns={old_col: new_col})
    if 'serving_size' not in food_df.columns:
        food_df['serving_size'] = 100
    numeric_cols = ['calories', 'protein', 'carbohydrates', 'fat', 'serving_size']
    for col in numeric_cols:
        if col in food_df.columns:
            food_df[col] = pd.to_numeric(food_df[col], errors='coerce')
    food_df = food_df.dropna(subset=['name', 'calories'])
except Exception as e:
    print(f"Error loading dataset: {e}, using fallback data...")
    food_data = {
        'name': ['Aloo Gobi', 'Butter Chicken', 'Chana Masala', 'Dal Makhani', 'Palak Paneer',
                 'Roti', 'Naan', 'Basmati Rice', 'Idli', 'Dosa', 'Sambar', 'Raita', 'Biryani',
                 'Tandoori Chicken', 'Vada', 'Uttapam', 'Upma', 'Poha', 'Pav Bhaji', 'Chole Bhature'],
        'calories': [150, 325, 180, 230, 190, 120, 260, 150, 58, 133, 152, 75, 292, 165, 97, 
                     188, 185, 270, 210, 427],
        'protein': [3.5, 28, 7.5, 9, 11, 3, 9, 3.5, 2, 3.7, 3.8, 3.5, 9.5, 31, 2.2, 
                    5.3, 3.5, 5.2, 6, 13.2],
        'carbohydrates': [15, 10, 30, 31, 6, 18, 33, 32, 12, 25.2, 28, 3.5, 46, 0, 16.3, 
                          28.5, 31, 44, 22.7, 57.2],
        'fat': [8, 17, 6, 9, 12.5, 3.7, 11, 0.5, 0.2, 3.8, 5.6, 5, 9, 3.6, 3.9, 
                7.2, 7, 12, 12, 20],
        'serving_size': [100, 100, 100, 100, 100, 30, 80, 100, 40, 100, 100, 100, 100, 100, 35, 
                         100, 100, 100, 100, 120],
        'food_group': ['Vegetable', 'Protein', 'Protein', 'Protein', 'Protein', 'Grain', 'Grain', 
                       'Grain', 'Grain', 'Grain', 'Vegetable', 'Dairy', 'Mixed', 'Protein', 'Snack',
                       'Grain', 'Grain', 'Grain', 'Mixed', 'Mixed']
    }
    food_df = pd.DataFrame(food_data)

# Sample recipe database (could be expanded)
recipes = {
    'Aloo Gobi': "Ingredients: Potatoes, Cauliflower, Spices\nInstructions: Sauté spices, add veggies, cook until tender.",
    'Butter Chicken': "Ingredients: Chicken, Butter, Cream, Spices\nInstructions: Marinate chicken, cook with sauce.",
    'Idli': "Ingredients: Rice, Urad Dal\nInstructions: Ferment batter, steam in molds."
}

# Calculate caloric needs (Harris-Benedict Equation)
def calculate_caloric_needs(weight, height, age, gender, activity_level):
    if not all(isinstance(x, (int, float)) and x > 0 for x in [weight, height, age]):
        raise gr.Error("Weight, height, and age must be positive numbers")
    if gender.lower() == 'male':
        bmr = 88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age)
    else:
        bmr = 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age)
    activity_multipliers = {'sedentary': 1.2, 'lightly active': 1.375, 'moderately active': 1.55, 
                            'very active': 1.725, 'extra active': 1.9}
    return round(bmr * activity_multipliers[activity_level.lower()])

# Calculate macronutrients
def calculate_macros(caloric_needs, goal):
    macros = {}
    if goal.lower() == 'weight loss':
        caloric_needs = caloric_needs * 0.85
        macros['protein'] = (caloric_needs * 0.30) / 4
        macros['fat'] = (caloric_needs * 0.30) / 9
        macros['carbs'] = (caloric_needs * 0.40) / 4
    elif goal.lower() == 'maintenance':
        macros['protein'] = (caloric_needs * 0.25) / 4
        macros['fat'] = (caloric_needs * 0.30) / 9
        macros['carbs'] = (caloric_needs * 0.45) / 4
    elif goal.lower() == 'muscle gain':
        caloric_needs = caloric_needs * 1.10
        macros['protein'] = (caloric_needs * 0.30) / 4
        macros['fat'] = (caloric_needs * 0.25) / 9
        macros['carbs'] = (caloric_needs * 0.45) / 4
    return {'calories': round(caloric_needs), 'protein': round(macros['protein']), 
            'carbs': round(macros['carbs']), 'fat': round(macros['fat'])}

# Recommend meals
def recommend_meals(caloric_needs, macros, restrictions, meals_per_day, meal_preferences):
    filtered_foods = food_df.copy()
    if 'vegetarian' in restrictions:
        filtered_foods = filtered_foods[~filtered_foods['food_group'].str.contains('Non-veg|Meat', case=False, na=False)]
    if 'vegan' in restrictions:
        filtered_foods = filtered_foods[~filtered_foods['food_group'].str.contains('Non-veg|Meat|Dairy', case=False, na=False)]
    if len(filtered_foods) < 10:
        filtered_foods = food_df.copy()
    
    meal_types = {"Breakfast": ["Idli", "Dosa", "Poha", "Upma"], "Lunch": ["Rice", "Dal", "Roti", "Biryani"],
                  "Dinner": ["Roti", "Sabzi", "Dal"], "Snack": ["Vada", "Samosa"]}
    per_meal_calories = caloric_needs / meals_per_day
    meal_plan = []
    daily_meal_names = ["Breakfast", "Lunch", "Evening Snack", "Dinner"][:meals_per_day]
    if meals_per_day > len(daily_meal_names):
        daily_meal_names.extend([f"Meal {i+1}" for i in range(len(daily_meal_names), meals_per_day)])
    
    for meal_name in daily_meal_names:
        meal_category = next((k for k, v in meal_types.items() if meal_name in k), "Lunch")
        potential_items = filtered_foods[filtered_foods['name'].str.contains('|'.join(meal_types.get(meal_category, [])), 
                                                                            case=False, na=False)] if meal_types.get(meal_category) else filtered_foods
        if len(potential_items) < 5:
            potential_items = filtered_foods
        num_items = np.random.randint(2, 5)
        selected_food_items = potential_items.sample(min(num_items, len(potential_items)))
        
        selected_items = []
        current_nutrition = {'calories': 0, 'protein': 0, 'carbs': 0, 'fat': 0}
        for _, food in selected_food_items.iterrows():
            serving_multiplier = 1.0
            food_name = food.get('name', "Unknown")
            serving_size = food.get('serving_size', 100) * serving_multiplier
            item_calories = food.get('calories', 0) * serving_multiplier
            item_protein = food.get('protein', 0) * serving_multiplier
            item_carbs = food.get('carbohydrates', 0) * serving_multiplier
            item_fat = food.get('fat', 0) * serving_multiplier
            current_nutrition['calories'] += item_calories
            current_nutrition['protein'] += item_protein
            current_nutrition['carbs'] += item_carbs
            current_nutrition['fat'] += item_fat
            selected_items.append({'name': food_name, 'serving': round(serving_size), 'calories': item_calories, 
                                   'protein': item_protein, 'carbs': item_carbs, 'fat': item_fat})
        
        if current_nutrition['calories'] > 0:
            scaling_factor = per_meal_calories / current_nutrition['calories']
            for item in selected_items:
                item['serving'] = round(item['serving'] * scaling_factor)
                item['calories'] = item['calories'] * scaling_factor
                item['protein'] = item['protein'] * scaling_factor
                item['carbs'] = item['carbs'] * scaling_factor
                item['fat'] = item['fat'] * scaling_factor
            current_nutrition = {k: sum(item[k] for item in selected_items) for k in ['calories', 'protein', 'carbs', 'fat']}
        
        meal_plan.append({'name': meal_name, 'items': selected_items, 
                          'nutrition': {k: round(v) for k, v in current_nutrition.items()}})
    return meal_plan

# Format meal plan with recipes
def format_meal_plan(meal_plan, daily_targets):
    output = "# Your Personalized Indian Meal Plan\n\n"
    output += f"## Daily Targets: {daily_targets['calories']} kcal, {daily_targets['protein']}g protein, {daily_targets['carbs']}g carbs, {daily_targets['fat']}g fat\n\n"
    total_nutrition = {'calories': 0, 'protein': 0, 'carbs': 0, 'fat': 0}
    
    for meal in meal_plan:
        output += f"### {meal['name']}\n"
        for item in meal['items']:
            output += f"- {item['name']} ({item['serving']}g) - {round(item['calories'])} kcal\n"
            if item['name'] in recipes:
                output += f"  *Recipe*: {recipes[item['name']]}\n"
        nutrition = meal['nutrition']
        total_nutrition = {k: total_nutrition[k] + v for k, v in nutrition.items()}
        output += f"\n**Nutrition:** {nutrition['calories']} kcal, {nutrition['protein']}g protein, {nutrition['carbs']}g carbs, {nutrition['fat']}g fat\n\n"
    
    output += f"## Summary: {total_nutrition['calories']} kcal, {total_nutrition['protein']}g protein, {total_nutrition['carbs']}g carbs, {total_nutrition['fat']}g fat\n"
    return output

# Main function
def create_nutrition_plan(weight, height, age, gender, activity_level, goal, dietary_restrictions, meals_per_day, regional_preference):
    caloric_needs = calculate_caloric_needs(weight, height, age, gender, activity_level)
    macros = calculate_macros(caloric_needs, goal)
    restrictions = dietary_restrictions.lower().split(', ') if dietary_restrictions else []
    meal_plan = recommend_meals(macros['calories'], macros, restrictions, meals_per_day, regional_preference)
    return format_meal_plan(meal_plan, macros)

# Progress tracking (simple example)
progress_data = {'dates': [], 'calories': []}
def track_progress(calories_consumed):
    progress_data['dates'].append(pd.Timestamp.now().strftime('%Y-%m-%d'))
    progress_data['calories'].append(float(calories_consumed))
    fig, ax = plt.subplots()
    ax.plot(progress_data['dates'], progress_data['calories'], marker='o')
    ax.set_xlabel("Date")
    ax.set_ylabel("Calories Consumed")
    plt.xticks(rotation=45)
    return fig

# Social sharing
def share_plan(plan):
    return f"Check out my Indian Meal Plan!\n\n{plan}"

# Gradio Interface
with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", secondary_hue="green"), 
               css=".gr-button {border-radius: 10px;} .header {color: #FF5733; font-size: 2em;}") as app:
    gr.Markdown("# Indian Cuisine Nutrition Planner", elem_classes="header")
    gr.Markdown("Plan your meals with authentic Indian flavors!")
    
    with gr.Row():
        with gr.Column(scale=1, min_width=300):
            weight = gr.Number(label="Weight (kg)", value=70)
            height = gr.Number(label="Height (cm)", value=170)
            age = gr.Number(label="Age", value=30)
            gender = gr.Radio(["Male", "Female"], label="Gender", value="Male")
            activity_level = gr.Dropdown(["Sedentary", "Lightly Active", "Moderately Active", 
                                        "Very Active", "Extra Active"], label="Activity Level", 
                                        value="Moderately Active")
        
        with gr.Column(scale=1, min_width=300):
            goal = gr.Radio(["Weight Loss", "Maintenance", "Muscle Gain"], label="Goal", value="Maintenance")
            dietary_restrictions = gr.Textbox(label="Dietary Restrictions (e.g., vegetarian)", value="")
            meals_per_day = gr.Slider(2, 6, value=3, step=1, label="Meals per Day")
            regional_preference = gr.Dropdown(["All", "North Indian", "South Indian", "East Indian", 
                                             "West Indian"], label="Regional Preference", value="All")
            submit_btn = gr.Button("Generate Plan", variant="primary")

    with gr.Row():
        output = gr.Markdown(label="Your Meal Plan")
    
    with gr.Tab("Track Progress"):
        calories_input = gr.Number(label="Log Today's Calories")
        track_btn = gr.Button("Add to Progress")
        progress_plot = gr.Plot(label="Calorie Progress")
    
    with gr.Tab("Share"):
        share_btn = gr.Button("Generate Shareable Plan")
        share_output = gr.Textbox(label="Share this with friends!")

    submit_btn.click(fn=create_nutrition_plan, 
                     inputs=[weight, height, age, gender, activity_level, goal, dietary_restrictions, 
                             meals_per_day, regional_preference], 
                     outputs=output)
    track_btn.click(fn=track_progress, inputs=calories_input, outputs=progress_plot)
    share_btn.click(fn=share_plan, inputs=output, outputs=share_output)

app.launch(debug=True)