Spaces:
Sleeping
Sleeping
| 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) |