Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -31,7 +31,7 @@ GI_RANGES = {
|
|
31 |
"high": (70, 100)
|
32 |
}
|
33 |
|
34 |
-
# Utility Functions (unchanged
|
35 |
def estimate_gi_timing(gi_value: Optional[int]) -> tuple[float, float]:
|
36 |
if gi_value is None:
|
37 |
return 1.0, 2.5
|
@@ -77,12 +77,16 @@ def classify_food(image):
|
|
77 |
print(f"Classify food error: {e}")
|
78 |
return "unknown"
|
79 |
|
80 |
-
def get_food_nutrition(food_name: str, food_data: pd.DataFrame, weight_grams: Optional[float] = None) -> Optional[Dict[str, Any]]:
|
81 |
food_name_lower = food_name.lower().strip()
|
82 |
matches = get_close_matches(food_name_lower, food_data['food_name'].tolist(), n=1, cutoff=0.6)
|
|
|
83 |
|
84 |
if matches:
|
85 |
-
|
|
|
|
|
|
|
86 |
base_carbs = float(matched_row.get('unit_serving_carb_g', matched_row.get('carb_g', 0.0)))
|
87 |
serving_size = matched_row.get('servings_unit', 'unknown')
|
88 |
gi_value = matched_row.get('glycemic_index', None)
|
@@ -94,10 +98,9 @@ def get_food_nutrition(food_name: str, food_data: pd.DataFrame, weight_grams: Op
|
|
94 |
except (ValueError, TypeError):
|
95 |
gi_value = None
|
96 |
|
97 |
-
# Adjust portion based on weight in grams if provided
|
98 |
if weight_grams and serving_size != 'unknown':
|
99 |
try:
|
100 |
-
serving_weight = float(matched_row.get('serving_weight_grams', 100))
|
101 |
portion_size = weight_grams / serving_weight
|
102 |
except (ValueError, TypeError):
|
103 |
portion_size = 1.0
|
@@ -106,7 +109,7 @@ def get_food_nutrition(food_name: str, food_data: pd.DataFrame, weight_grams: Op
|
|
106 |
|
107 |
adjusted_carbs = base_carbs * portion_size
|
108 |
|
109 |
-
|
110 |
'matched_food': matched_row['food_name'],
|
111 |
'category': matched_row.get('primarysource', 'unknown'),
|
112 |
'subcategory': 'unknown',
|
@@ -117,7 +120,8 @@ def get_food_nutrition(food_name: str, food_data: pd.DataFrame, weight_grams: Op
|
|
117 |
'notes': 'none',
|
118 |
'glycemic_index': gi_value
|
119 |
}
|
120 |
-
|
|
|
121 |
|
122 |
def determine_gi_level(gi_value: Optional[int]) -> str:
|
123 |
if gi_value is None:
|
@@ -188,7 +192,7 @@ def calculate_insulin_needs(carbs: float, glucose_current: float, glucose_target
|
|
188 |
}
|
189 |
|
190 |
def create_detailed_report(nutrition_info: Dict[str, Any], insulin_info: Dict[str, Any],
|
191 |
-
current_basal_rate: float) -> tuple[str, str, str]:
|
192 |
gi_level = determine_gi_level(nutrition_info.get('glycemic_index'))
|
193 |
peak_time, duration = estimate_gi_timing(nutrition_info.get('glycemic_index'))
|
194 |
|
@@ -203,6 +207,7 @@ def create_detailed_report(nutrition_info: Dict[str, Any], insulin_info: Dict[st
|
|
203 |
- Carbs per Serving: {nutrition_info['base_carbs']}g
|
204 |
- Portion Multiplier: {nutrition_info['portion_multiplier']}x
|
205 |
- Total Carbs: {nutrition_info['adjusted_carbs']}g
|
|
|
206 |
"""
|
207 |
|
208 |
insulin_details = f"""
|
@@ -235,17 +240,15 @@ def diabetes_dashboard(initial_glucose, food_image, food_name_input, weight_gram
|
|
235 |
if food_data.empty:
|
236 |
return "Error loading food data", None, None, None, None
|
237 |
|
238 |
-
# Determine food name: use manual input if provided, otherwise classify from image
|
239 |
if food_name_input and food_name_input.strip():
|
240 |
food_name = food_name_input.strip()
|
241 |
else:
|
242 |
food_name = classify_food(food_image)
|
243 |
|
244 |
-
|
245 |
-
nutrition_info = get_food_nutrition(food_name, food_data, weight_grams)
|
246 |
|
247 |
if not nutrition_info:
|
248 |
-
return
|
249 |
|
250 |
try:
|
251 |
basal_rates = json.loads(basal_rates_input)
|
@@ -261,9 +264,8 @@ def diabetes_dashboard(initial_glucose, food_image, food_name_input, weight_gram
|
|
261 |
return insulin_info['error'], None, None, None, None
|
262 |
|
263 |
current_basal_rate = get_basal_rate(12, basal_rates)
|
264 |
-
glucose_meal_details, insulin_details, basal_details = create_detailed_report(nutrition_info, insulin_info, current_basal_rate)
|
265 |
|
266 |
-
# Glucose Prediction (unchanged)
|
267 |
hours = list(range(time_hours))
|
268 |
glucose_levels = []
|
269 |
current_glucose = initial_glucose
|
@@ -291,7 +293,7 @@ def diabetes_dashboard(initial_glucose, food_image, food_name_input, weight_gram
|
|
291 |
|
292 |
return glucose_meal_details, insulin_details, basal_details, insulin_info['total_bolus'], fig
|
293 |
|
294 |
-
#
|
295 |
with gr.Blocks(title="Type 1 Diabetes Management Dashboard") as app:
|
296 |
gr.Markdown("# Type 1 Diabetes Management Dashboard")
|
297 |
|
|
|
31 |
"high": (70, 100)
|
32 |
}
|
33 |
|
34 |
+
# Utility Functions (mostly unchanged)
|
35 |
def estimate_gi_timing(gi_value: Optional[int]) -> tuple[float, float]:
|
36 |
if gi_value is None:
|
37 |
return 1.0, 2.5
|
|
|
77 |
print(f"Classify food error: {e}")
|
78 |
return "unknown"
|
79 |
|
80 |
+
def get_food_nutrition(food_name: str, food_data: pd.DataFrame, weight_grams: Optional[float] = None) -> tuple[Optional[Dict[str, Any]], str]:
|
81 |
food_name_lower = food_name.lower().strip()
|
82 |
matches = get_close_matches(food_name_lower, food_data['food_name'].tolist(), n=1, cutoff=0.6)
|
83 |
+
correction_note = ""
|
84 |
|
85 |
if matches:
|
86 |
+
corrected_name = matches[0]
|
87 |
+
if corrected_name != food_name_lower:
|
88 |
+
correction_note = f"Note: '{food_name}' corrected to '{corrected_name}'"
|
89 |
+
matched_row = food_data[food_data['food_name'] == corrected_name].iloc[0]
|
90 |
base_carbs = float(matched_row.get('unit_serving_carb_g', matched_row.get('carb_g', 0.0)))
|
91 |
serving_size = matched_row.get('servings_unit', 'unknown')
|
92 |
gi_value = matched_row.get('glycemic_index', None)
|
|
|
98 |
except (ValueError, TypeError):
|
99 |
gi_value = None
|
100 |
|
|
|
101 |
if weight_grams and serving_size != 'unknown':
|
102 |
try:
|
103 |
+
serving_weight = float(matched_row.get('serving_weight_grams', 100))
|
104 |
portion_size = weight_grams / serving_weight
|
105 |
except (ValueError, TypeError):
|
106 |
portion_size = 1.0
|
|
|
109 |
|
110 |
adjusted_carbs = base_carbs * portion_size
|
111 |
|
112 |
+
nutrition_info = {
|
113 |
'matched_food': matched_row['food_name'],
|
114 |
'category': matched_row.get('primarysource', 'unknown'),
|
115 |
'subcategory': 'unknown',
|
|
|
120 |
'notes': 'none',
|
121 |
'glycemic_index': gi_value
|
122 |
}
|
123 |
+
return nutrition_info, correction_note
|
124 |
+
return None, f"No close match found for '{food_name}'"
|
125 |
|
126 |
def determine_gi_level(gi_value: Optional[int]) -> str:
|
127 |
if gi_value is None:
|
|
|
192 |
}
|
193 |
|
194 |
def create_detailed_report(nutrition_info: Dict[str, Any], insulin_info: Dict[str, Any],
|
195 |
+
current_basal_rate: float, correction_note: str) -> tuple[str, str, str]:
|
196 |
gi_level = determine_gi_level(nutrition_info.get('glycemic_index'))
|
197 |
peak_time, duration = estimate_gi_timing(nutrition_info.get('glycemic_index'))
|
198 |
|
|
|
207 |
- Carbs per Serving: {nutrition_info['base_carbs']}g
|
208 |
- Portion Multiplier: {nutrition_info['portion_multiplier']}x
|
209 |
- Total Carbs: {nutrition_info['adjusted_carbs']}g
|
210 |
+
{correction_note}
|
211 |
"""
|
212 |
|
213 |
insulin_details = f"""
|
|
|
240 |
if food_data.empty:
|
241 |
return "Error loading food data", None, None, None, None
|
242 |
|
|
|
243 |
if food_name_input and food_name_input.strip():
|
244 |
food_name = food_name_input.strip()
|
245 |
else:
|
246 |
food_name = classify_food(food_image)
|
247 |
|
248 |
+
nutrition_info, correction_note = get_food_nutrition(food_name, food_data, weight_grams)
|
|
|
249 |
|
250 |
if not nutrition_info:
|
251 |
+
return correction_note, None, None, None, None
|
252 |
|
253 |
try:
|
254 |
basal_rates = json.loads(basal_rates_input)
|
|
|
264 |
return insulin_info['error'], None, None, None, None
|
265 |
|
266 |
current_basal_rate = get_basal_rate(12, basal_rates)
|
267 |
+
glucose_meal_details, insulin_details, basal_details = create_detailed_report(nutrition_info, insulin_info, current_basal_rate, correction_note)
|
268 |
|
|
|
269 |
hours = list(range(time_hours))
|
270 |
glucose_levels = []
|
271 |
current_glucose = initial_glucose
|
|
|
293 |
|
294 |
return glucose_meal_details, insulin_details, basal_details, insulin_info['total_bolus'], fig
|
295 |
|
296 |
+
# Gradio Interface (unchanged)
|
297 |
with gr.Blocks(title="Type 1 Diabetes Management Dashboard") as app:
|
298 |
gr.Markdown("# Type 1 Diabetes Management Dashboard")
|
299 |
|