Answer with cooking plan and save edamam API tokens
Build, push image, and notify Watchtower / build-image (push) Successful in 3m59s
Build, push image, and notify Watchtower / notify (push) Successful in 7s

This commit is contained in:
2026-07-27 14:37:05 +02:00
parent 6a42e4a772
commit 81de985580
3 changed files with 1006 additions and 3 deletions
+895
View File
@@ -1,9 +1,11 @@
import os import os
import requests import requests
from typing import Dict, Any, Optional from typing import Dict, Any, Optional
import json
EDAMAM_APP_ID__FOOD = os.getenv("EDAMAM_APP_ID__FOOD", None) EDAMAM_APP_ID__FOOD = os.getenv("EDAMAM_APP_ID__FOOD", None)
EDAMAM_APP_KEY__FOOD = os.getenv("EDAMAM_APP_KEY__FOOD", None) EDAMAM_APP_KEY__FOOD = os.getenv("EDAMAM_APP_KEY__FOOD", None)
SAVE_EDAMAM_API_TOKEN = os.getenv("SAVE_EDAMAM_API_TOKEN", False)
class EdamamAPI: class EdamamAPI:
"""Wrapper around Edamam Food Database API 2.0 (Vision & Nutrients)""" """Wrapper around Edamam Food Database API 2.0 (Vision & Nutrients)"""
@@ -14,6 +16,899 @@ class EdamamAPI:
pass pass
def analyze_dish_image(self, image_file_path: str): def analyze_dish_image(self, image_file_path: str):
if SAVE_EDAMAM_API_TOKEN:
return json.loads("""
{
"combined": {
"problems": [],
"recipe": {
"calories": 306,
"cautions": [
"GLUTEN",
"WHEAT",
"MILK",
"SULFITES",
"FODMAP"
],
"dietLabels": [],
"healthLabels": [
"EGG_FREE",
"PEANUT_FREE",
"TREE_NUT_FREE",
"SOY_FREE",
"FISH_FREE",
"SHELLFISH_FREE",
"CRUSTACEAN_FREE",
"CELERY_FREE",
"MUSTARD_FREE",
"SESAME_FREE",
"LUPINE_FREE",
"MOLLUSK_FREE",
"ALCOHOL_FREE"
],
"ingredientLines": [
"90 g (3 oz) Beef chunks",
"100 g (0.75 cup) Potatoes, cubed",
"40 g (0.33 cup) Carrots, sliced",
"30 g (0.25 cup) Green beans",
"120 g (0.5 cup) Brown gravy or stew sauce",
"Salt and pepper to taste"
],
"label": "Beef Stew with Vegetables (Frozen Meal)",
"totalDaily": {
"CA": {
"label": "Calcium",
"quantity": 9.808827779627787,
"unit": "%"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 9.07220373540042,
"unit": "%"
},
"CHOCDF.net": {
"label": "Carbohydrates (net)",
"quantity": 0.0,
"unit": "g"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 20.837056709550403,
"unit": "%"
},
"ENERC_KCAL": {
"label": "Energy",
"quantity": 13.100053025164515,
"unit": "%"
},
"FASAT": {
"label": "Saturated",
"quantity": 17.148508115376796,
"unit": "%"
},
"FAT": {
"label": "Fat",
"quantity": 14.902089676480887,
"unit": "%"
},
"FE": {
"label": "Iron",
"quantity": 21.951689781236098,
"unit": "%"
},
"FIBTG": {
"label": "Fiber",
"quantity": 13.858671762525935,
"unit": "%"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 10.817828789332737,
"unit": "%"
},
"K": {
"label": "Potassium",
"quantity": 28.904445650775536,
"unit": "%"
},
"MG": {
"label": "Magnesium",
"quantity": 15.863016599088612,
"unit": "%"
},
"NA": {
"label": "Sodium",
"quantity": 60.46248,
"unit": "%"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 66.37252070251446,
"unit": "%"
},
"P": {
"label": "Phosphorus",
"quantity": 25.034580972170218,
"unit": "%"
},
"PROCNT": {
"label": "Protein",
"quantity": 21.91938193709794,
"unit": "%"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 73.88477475545037,
"unit": "%"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 84.12049444050538,
"unit": "%"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 12.990953399638641,
"unit": "%"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 45.87938825251855,
"unit": "%"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 113.07016020542191,
"unit": "%"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 90.1530888403073,
"unit": "%"
},
"VITC": {
"label": "Vitamin C",
"quantity": 35.18207820897409,
"unit": "%"
},
"VITD": {
"label": "Vitamin D",
"quantity": 13.66228503481425,
"unit": "%"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 27.534449511962567,
"unit": "%"
},
"ZN": {
"label": "Zinc",
"quantity": 55.091388643252344,
"unit": "%"
}
},
"totalNutrients": {
"CA": {
"label": "Calcium",
"quantity": 127.51476113516124,
"unit": "mg"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 26.573051753721295,
"unit": "g"
},
"CHOCDF.net": {
"label": "Carbohydrates (net)",
"quantity": 21.30675648396144,
"unit": "g"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 73.23964970198097,
"unit": "mg"
},
"ENERC_KCAL": {
"label": "Energy",
"quantity": 306.9669925121675,
"unit": "kcal"
},
"FAMS": {
"label": "Monounsaturated",
"quantity": 5.622055495052523,
"unit": "g"
},
"FAPU": {
"label": "Polyunsaturated",
"quantity": 1.5770619917608195,
"unit": "g"
},
"FASAT": {
"label": "Saturated",
"quantity": 4.0183241641356675,
"unit": "g"
},
"FAT": {
"label": "Fat",
"quantity": 11.639773878137946,
"unit": "g"
},
"FATRN": {
"label": "Trans",
"quantity": 0.24391676668519283,
"unit": "g"
},
"FE": {
"label": "Iron",
"quantity": 3.9513041606224975,
"unit": "mg"
},
"FIBTG": {
"label": "Fiber",
"quantity": 5.266295269759856,
"unit": "g"
},
"FOLAC": {
"label": "Folic acid",
"quantity": 18.024043373983595,
"unit": "\u00b5g"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 43.271315157330946,
"unit": "\u00b5g"
},
"FOLFD": {
"label": "Folate (food)",
"quantity": 40.54129806334046,
"unit": "\u00b5g"
},
"K": {
"label": "Potassium",
"quantity": 982.7511521263683,
"unit": "mg"
},
"MG": {
"label": "Magnesium",
"quantity": 66.62466971617216,
"unit": "mg"
},
"NA": {
"label": "Sodium",
"quantity": 906.9372000000001,
"unit": "mg"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 10.619603312402313,
"unit": "mg"
},
"P": {
"label": "Phosphorus",
"quantity": 312.93226215212775,
"unit": "mg"
},
"PROCNT": {
"label": "Protein",
"quantity": 25.68129586205237,
"unit": "g"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 0.9605020718208549,
"unit": "mg"
},
"SUGAR": {
"label": "Sugars",
"quantity": 8.053516658227332,
"unit": "g"
},
"SUGAR.added": {
"label": "Sugars, added",
"quantity": 2.3940423830596225,
"unit": "g"
},
"Sugar.alcohol": {
"label": "Sugar alcohol",
"quantity": 0.0,
"unit": "g"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 1.0094459332860646,
"unit": "mg"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 1.9486430099457963,
"unit": "mg"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 412.914494272667,
"unit": "\u00b5g"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 2.7136838449301255,
"unit": "\u00b5g"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 1.5326025102852243,
"unit": "mg"
},
"VITC": {
"label": "Vitamin C",
"quantity": 31.66387038807668,
"unit": "mg"
},
"VITD": {
"label": "Vitamin D",
"quantity": 2.73245700696285,
"unit": "\u00b5g"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 33.04133941435508,
"unit": "\u00b5g"
},
"WATER": {
"label": "Water",
"quantity": 321.1285604946806,
"unit": "g"
},
"ZN": {
"label": "Zinc",
"quantity": 6.060052750757758,
"unit": "mg"
}
},
"totalWeight": 390.7575715150228,
"translations": [
{
"id": "EGG_FREE",
"label": "Egg-Free",
"type": "health"
},
{
"id": "PEANUT_FREE",
"label": "Peanut-Free",
"type": "health"
},
{
"id": "TREE_NUT_FREE",
"label": "Tree-Nut-Free",
"type": "health"
},
{
"id": "SOY_FREE",
"label": "Soy-Free",
"type": "health"
},
{
"id": "FISH_FREE",
"label": "Fish-Free",
"type": "health"
},
{
"id": "SHELLFISH_FREE",
"label": "Shellfish-Free",
"type": "health"
},
{
"id": "CRUSTACEAN_FREE",
"label": "Crustacean-Free",
"type": "health"
},
{
"id": "CELERY_FREE",
"label": "Celery-Free",
"type": "health"
},
{
"id": "MUSTARD_FREE",
"label": "Mustard-Free",
"type": "health"
},
{
"id": "SESAME_FREE",
"label": "Sesame-Free",
"type": "health"
},
{
"id": "LUPINE_FREE",
"label": "Lupine-Free",
"type": "health"
},
{
"id": "MOLLUSK_FREE",
"label": "Mollusk-Free",
"type": "health"
},
{
"id": "ALCOHOL_FREE",
"label": "Alcohol-Free",
"type": "health"
},
{
"id": "GLUTEN",
"label": "Gluten",
"type": "caution"
},
{
"id": "WHEAT",
"label": "Wheat",
"type": "caution"
},
{
"id": "MILK",
"label": "Milk",
"type": "caution"
},
{
"id": "SULFITES",
"label": "Sulfites",
"type": "caution"
},
{
"id": "FODMAP",
"label": "FODMAP",
"type": "caution"
}
],
"uri": "http://www.edamam.com/ontologies/edamam.owl#recipe_e59b15e71cd34bf4b7c02c2f545e40f3",
"yield": 1.0
}
},
"dishes": [
{
"problems": [],
"recipe": {
"calories": 306,
"cautions": [
"GLUTEN",
"WHEAT",
"MILK",
"SULFITES",
"FODMAP"
],
"dietLabels": [],
"healthLabels": [
"EGG_FREE",
"PEANUT_FREE",
"TREE_NUT_FREE",
"SOY_FREE",
"FISH_FREE",
"SHELLFISH_FREE",
"CRUSTACEAN_FREE",
"CELERY_FREE",
"MUSTARD_FREE",
"SESAME_FREE",
"LUPINE_FREE",
"MOLLUSK_FREE",
"ALCOHOL_FREE"
],
"ingredientLines": [
"90 g (3 oz) Beef chunks",
"100 g (0.75 cup) Potatoes, cubed",
"40 g (0.33 cup) Carrots, sliced",
"30 g (0.25 cup) Green beans",
"120 g (0.5 cup) Brown gravy or stew sauce",
"Salt and pepper to taste"
],
"label": "Beef Stew with Vegetables (Frozen Meal)",
"totalDaily": {
"CA": {
"label": "Calcium",
"quantity": 9.808827779627787,
"unit": "%"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 9.07220373540042,
"unit": "%"
},
"CHOCDF.net": {
"label": "Carbohydrates (net)",
"quantity": 0.0,
"unit": "g"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 20.837056709550403,
"unit": "%"
},
"ENERC_KCAL": {
"label": "Energy",
"quantity": 13.100053025164515,
"unit": "%"
},
"FASAT": {
"label": "Saturated",
"quantity": 17.148508115376796,
"unit": "%"
},
"FAT": {
"label": "Fat",
"quantity": 14.902089676480887,
"unit": "%"
},
"FE": {
"label": "Iron",
"quantity": 21.951689781236098,
"unit": "%"
},
"FIBTG": {
"label": "Fiber",
"quantity": 13.858671762525935,
"unit": "%"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 10.817828789332737,
"unit": "%"
},
"K": {
"label": "Potassium",
"quantity": 28.904445650775536,
"unit": "%"
},
"MG": {
"label": "Magnesium",
"quantity": 15.863016599088612,
"unit": "%"
},
"NA": {
"label": "Sodium",
"quantity": 60.46248,
"unit": "%"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 66.37252070251446,
"unit": "%"
},
"P": {
"label": "Phosphorus",
"quantity": 25.034580972170218,
"unit": "%"
},
"PROCNT": {
"label": "Protein",
"quantity": 21.91938193709794,
"unit": "%"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 73.88477475545037,
"unit": "%"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 84.12049444050538,
"unit": "%"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 12.990953399638641,
"unit": "%"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 45.87938825251855,
"unit": "%"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 113.07016020542191,
"unit": "%"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 90.1530888403073,
"unit": "%"
},
"VITC": {
"label": "Vitamin C",
"quantity": 35.18207820897409,
"unit": "%"
},
"VITD": {
"label": "Vitamin D",
"quantity": 13.66228503481425,
"unit": "%"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 27.534449511962567,
"unit": "%"
},
"ZN": {
"label": "Zinc",
"quantity": 55.091388643252344,
"unit": "%"
}
},
"totalNutrients": {
"CA": {
"label": "Calcium",
"quantity": 127.51476113516124,
"unit": "mg"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 26.573051753721295,
"unit": "g"
},
"CHOCDF.net": {
"label": "Carbohydrates (net)",
"quantity": 21.30675648396144,
"unit": "g"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 73.23964970198097,
"unit": "mg"
},
"ENERC_KCAL": {
"label": "Energy",
"quantity": 306.9669925121675,
"unit": "kcal"
},
"FAMS": {
"label": "Monounsaturated",
"quantity": 5.622055495052523,
"unit": "g"
},
"FAPU": {
"label": "Polyunsaturated",
"quantity": 1.5770619917608195,
"unit": "g"
},
"FASAT": {
"label": "Saturated",
"quantity": 4.0183241641356675,
"unit": "g"
},
"FAT": {
"label": "Fat",
"quantity": 11.639773878137946,
"unit": "g"
},
"FATRN": {
"label": "Trans",
"quantity": 0.24391676668519283,
"unit": "g"
},
"FE": {
"label": "Iron",
"quantity": 3.9513041606224975,
"unit": "mg"
},
"FIBTG": {
"label": "Fiber",
"quantity": 5.266295269759856,
"unit": "g"
},
"FOLAC": {
"label": "Folic acid",
"quantity": 18.024043373983595,
"unit": "\u00b5g"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 43.271315157330946,
"unit": "\u00b5g"
},
"FOLFD": {
"label": "Folate (food)",
"quantity": 40.54129806334046,
"unit": "\u00b5g"
},
"K": {
"label": "Potassium",
"quantity": 982.7511521263683,
"unit": "mg"
},
"MG": {
"label": "Magnesium",
"quantity": 66.62466971617216,
"unit": "mg"
},
"NA": {
"label": "Sodium",
"quantity": 906.9372000000001,
"unit": "mg"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 10.619603312402313,
"unit": "mg"
},
"P": {
"label": "Phosphorus",
"quantity": 312.93226215212775,
"unit": "mg"
},
"PROCNT": {
"label": "Protein",
"quantity": 25.68129586205237,
"unit": "g"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 0.9605020718208549,
"unit": "mg"
},
"SUGAR": {
"label": "Sugars",
"quantity": 8.053516658227332,
"unit": "g"
},
"SUGAR.added": {
"label": "Sugars, added",
"quantity": 2.3940423830596225,
"unit": "g"
},
"Sugar.alcohol": {
"label": "Sugar alcohol",
"quantity": 0.0,
"unit": "g"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 1.0094459332860646,
"unit": "mg"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 1.9486430099457963,
"unit": "mg"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 412.914494272667,
"unit": "\u00b5g"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 2.7136838449301255,
"unit": "\u00b5g"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 1.5326025102852243,
"unit": "mg"
},
"VITC": {
"label": "Vitamin C",
"quantity": 31.66387038807668,
"unit": "mg"
},
"VITD": {
"label": "Vitamin D",
"quantity": 2.73245700696285,
"unit": "\u00b5g"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 33.04133941435508,
"unit": "\u00b5g"
},
"WATER": {
"label": "Water",
"quantity": 321.1285604946806,
"unit": "g"
},
"ZN": {
"label": "Zinc",
"quantity": 6.060052750757758,
"unit": "mg"
}
},
"totalWeight": 390.7575715150228,
"translations": [
{
"id": "EGG_FREE",
"label": "Egg-Free",
"type": "health"
},
{
"id": "PEANUT_FREE",
"label": "Peanut-Free",
"type": "health"
},
{
"id": "TREE_NUT_FREE",
"label": "Tree-Nut-Free",
"type": "health"
},
{
"id": "SOY_FREE",
"label": "Soy-Free",
"type": "health"
},
{
"id": "FISH_FREE",
"label": "Fish-Free",
"type": "health"
},
{
"id": "SHELLFISH_FREE",
"label": "Shellfish-Free",
"type": "health"
},
{
"id": "CRUSTACEAN_FREE",
"label": "Crustacean-Free",
"type": "health"
},
{
"id": "CELERY_FREE",
"label": "Celery-Free",
"type": "health"
},
{
"id": "MUSTARD_FREE",
"label": "Mustard-Free",
"type": "health"
},
{
"id": "SESAME_FREE",
"label": "Sesame-Free",
"type": "health"
},
{
"id": "LUPINE_FREE",
"label": "Lupine-Free",
"type": "health"
},
{
"id": "MOLLUSK_FREE",
"label": "Mollusk-Free",
"type": "health"
},
{
"id": "ALCOHOL_FREE",
"label": "Alcohol-Free",
"type": "health"
},
{
"id": "GLUTEN",
"label": "Gluten",
"type": "caution"
},
{
"id": "WHEAT",
"label": "Wheat",
"type": "caution"
},
{
"id": "MILK",
"label": "Milk",
"type": "caution"
},
{
"id": "SULFITES",
"label": "Sulfites",
"type": "caution"
},
{
"id": "FODMAP",
"label": "FODMAP",
"type": "caution"
}
],
"uri": "http://www.edamam.com/ontologies/edamam.owl#recipe_e59b15e71cd34bf4b7c02c2f545e40f3",
"yield": 1.0
}
}
]
}
""")
url = "https://api.edamam.com/api/vision/v1/nutrients" url = "https://api.edamam.com/api/vision/v1/nutrients"
# Query parameters as specified by the YAML schema # Query parameters as specified by the YAML schema
+13 -3
View File
@@ -5,6 +5,7 @@ from flask import Flask, request, jsonify
from pymongo import MongoClient from pymongo import MongoClient
from APIs import generate, EdamamAPI from APIs import generate, EdamamAPI
import sys import sys
from microwaveCookPlanner import MicrowaveCookPlanner
sys.path.insert(0, '..') sys.path.insert(0, '..')
try: try:
from shared import config from shared import config
@@ -28,6 +29,11 @@ device_network_collection = db["device_network"]
CAMERA_IMAGE_DIR = "storage/dishCameraImages" CAMERA_IMAGE_DIR = "storage/dishCameraImages"
os.makedirs(CAMERA_IMAGE_DIR, exist_ok=True) os.makedirs(CAMERA_IMAGE_DIR, exist_ok=True)
# ---------------------------------------------------------
# Classes
# ---------------------------------------------------------
microwave_cook_planner = MicrowaveCookPlanner()
# --------------------------------------------------------- # ---------------------------------------------------------
# Routes # Routes
# --------------------------------------------------------- # ---------------------------------------------------------
@@ -72,14 +78,18 @@ def cooking_params():
# Remove the Mongo-injected '_id' object before returning the response # Remove the Mongo-injected '_id' object before returning the response
data.pop("_id", None) data.pop("_id", None)
return jsonify({"message": "Cooking parameters saved successfully", "data": data}), 201
except Exception as e: except Exception as e:
return jsonify({"error": f"Database error: {str(e)}"}), 500 return jsonify({"error": f"Database error: {str(e)}"}), 500
# 3. Returns with the cooking parameters # 3. Returns with the cooking parameters
cooking_plan = microwave_cook_planner.generate_plan(
image_path=data.get("camera_image"),
height_cm=data.get("height_cm", 4.0),
initial_temp_c=data.get("initial_temp_c", 20.0),
microwave_wattage=data.get("microwave_wattage", 900)
)
return jsonify(cooking_plan), 201
@app.route("/device-network", methods=["POST"]) @app.route("/device-network", methods=["POST"])
def device_network(): def device_network():
+98
View File
@@ -0,0 +1,98 @@
from typing import Dict, Any
from APIs.edamam import EdamamAPI
from microwaveDishAnalyzer import MicrowaveDishAnalyzer
from microwaveThermalEngine import MicrowaveThermalEngine, DishThermalState
class MicrowaveCookPlanner:
"""Orchestrates Edamam API, Dish Analyzer, and Thermal Engine into a single workflow."""
def __init__(self, cm_per_pixel: float = 0.05):
self.edamam_api = EdamamAPI()
self.analyzer = MicrowaveDishAnalyzer(cm_per_pixel=cm_per_pixel)
self.engine = MicrowaveThermalEngine()
def _extract_edamam_data(self, edamam_resp: Dict[str, Any]) -> tuple[str, float, Dict[str, float]]:
"""Parses Edamam Vision response to extract label, total mass, and macronutrient grams."""
recipe = edamam_resp.get("combined", {}).get("recipe", {})
# Fallback to first dish if 'combined' is empty
if not recipe and edamam_resp.get("dishes"):
recipe = edamam_resp["dishes"][0].get("recipe", {})
label = recipe.get("label", "Unknown Dish")
total_weight = float(recipe.get("totalWeight", 300.0)) # Default 300g fallback
nutrients = recipe.get("totalNutrients", {})
# Extract macronutrients in grams (Edamam nutrient codes)
fat_g = float(nutrients.get("FAT", {}).get("quantity", 0.0))
protein_g = float(nutrients.get("PROCNT", {}).get("quantity", 0.0))
carbs_g = float(nutrients.get("CHOCDF", {}).get("quantity", 0.0))
# Water is sometimes omitted in Edamam; infer remaining mass as water if missing
if "WATER" in nutrients:
water_g = float(nutrients["WATER"].get("quantity", 0.0))
else:
water_g = max(0.0, total_weight - (fat_g + protein_g + carbs_g))
macros = {
"water_g": water_g,
"fat_g": fat_g,
"protein_g": protein_g,
"carbs_g": carbs_g,
}
return label, total_weight, macros
def generate_plan(
self,
image_path: str,
height_cm: float,
initial_temp_c: float,
microwave_wattage: int = 900
) -> Dict[str, Any]:
"""Main pipeline call to parse an image and return cooking parameters."""
# 1. Vision & Nutrient Analysis
edamam_resp = self.edamam_api.analyze_dish_image(image_path)
food_label, edamam_mass_g, macros = self._extract_edamam_data(edamam_resp)
# 2. Geometric Volume Calculation
vol_data = self.analyzer.estimate_volume(
image_path=image_path,
height_cm=height_cm,
food_label=food_label
)
# 3. Mass Cross-Validation & Density Check
mass_data = self.analyzer.reconcile_mass(
edamam_mass_g=edamam_mass_g,
volume_cm3=vol_data["volume_cm3"],
food_label=food_label
)
final_mass_g = mass_data["final_mass_g"]
# 4. Thermal State Creation
thermal_state = DishThermalState(
food_name=food_label,
macronutrients=macros,
estimated_mass_g=final_mass_g,
initial_temp_c=initial_temp_c,
volume_cm3=vol_data["volume_cm3"]
)
# 5. Cook Plan Calculation
cook_plan = self.engine.calculate_cook_plan(
state=thermal_state,
microwave_wattage=microwave_wattage
)
# Return consolidated output
return {
"dish_name": food_label,
"reconciled_mass_g": final_mass_g,
"mass_validation_status": mass_data["status"],
"cook_plan": cook_plan,
"geometry": vol_data
}