Anupam007 commited on
Commit
e00b69c
·
verified ·
1 Parent(s): fc8d19a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -68
app.py CHANGED
@@ -30,26 +30,67 @@ DEFAULT_BASAL_RATES = {
30
  "18:00-24:00": 0.7
31
  }
32
 
 
 
 
33
  # -------------------------------------------------
34
  # Load Food Data from Hugging Face Dataset
35
  # -------------------------------------------------
36
 
37
  def load_food_data(dataset_name="Anupam007/Diabetic", local_csv="food_data.csv"):
 
38
  try:
39
- ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  return food_data
41
 
42
  except Exception as e:
43
  print(f"Error loading data: {e}")
44
  # Provide minimal default data in case of error
45
  food_data = pd.DataFrame({
46
- 'food_category': ['unknown'],
47
- 'food_subcategory': ['unknown'],
48
- 'food_name': ['unknown'], # lowercase default
49
- 'serving_description': ['unknown'],
50
- 'serving_amount': [1],
51
- 'serving_unit': ['serving'],
52
- 'carbohydrate_grams': [0],
53
  'notes': ['default']
54
  })
55
  return food_data
@@ -72,39 +113,60 @@ except Exception as e:
72
  processor = None
73
  model = None
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  def classify_food(image):
76
- """Classify food image using the pre-trained model"""
77
- print("classify_food function called") # Check if this function is even called
 
 
 
 
78
  try:
79
  if not model_loaded:
80
- print("Model not loaded, returning 'Unknown'")
81
- return "Unknown"
82
-
83
- print(f"Image type: {type(image)}") # Check the type of the image
84
 
85
  if isinstance(image, np.ndarray):
86
- print("Image is a numpy array, converting to PIL Image")
87
  image = Image.fromarray(image)
88
 
89
- print(f"Image mode: {image.mode}") # Check image mode (e.g., RGB, L)
90
-
91
  image = processor(images=image, return_tensors="pt")
92
- print(f"Processed image: {image}") # Print the output of the processor
93
 
94
  with torch.no_grad():
95
  outputs = model(**image)
96
  predicted_idx = torch.argmax(outputs.logits, dim=-1).item()
97
- food_name = model.config.id2label.get(predicted_idx, "Unknown Food")
98
- print(f"Predicted food name: {food_name}") # Print the predicted food name
99
- return food_name.lower() # Convert classification to lowercase
 
 
 
 
 
100
 
101
  except Exception as e:
102
- print(f"Classify food error: {e}") # Print the full error message
103
- return "Unknown" # If an exception arises make sure to create a default case
104
 
105
 
106
  def get_food_nutrition(food_name: str, food_data, portion_size: float = 1.0) -> Optional[Dict[str, Any]]:
107
  """Get carbohydrate content for the given food""" #No USDA anymore
 
 
108
  try:
109
  # First try the local CSV database
110
  food_name_lower = food_name.lower() # Ensure input is also lowercase
@@ -319,53 +381,26 @@ def diabetes_dashboard(initial_glucose, food_image, stress_level, sleep_hours, t
319
 
320
  # 1. Food Classification and Carb Calculation
321
  food_name = classify_food(food_image) # This line is now inside the function
 
 
 
 
 
 
 
 
 
 
322
  print(f"Classified food name: {food_name}") # Debugging: What is classified as? # Corrected indentation
323
  nutrition_info = get_food_nutrition(food_name, food_data, portion_size) # Changed to pass in data
324
  if not nutrition_info:
325
- # Try with generic categories if specific food not found
326
- generic_terms = food_name.split()
327
- for term in generic_terms:
328
- nutrition_info = get_food_nutrition(term, food_data, portion_size) # Changed to pass in data
329
- if nutrition_info:
330
- break
331
-
332
- if not nutrition_info:
333
- # Food not found, add to DataFrame if user provided the data
334
- if new_food_name:
335
- new_row = pd.DataFrame([{
336
- 'food_category': new_food_category,
337
- 'food_subcategory': new_food_subcategory,
338
- 'food_name': new_food_name.lower(), # Ensure lowercase
339
- 'serving_description': new_serving_description,
340
- 'serving_amount': new_serving_amount,
341
- 'serving_unit': new_serving_unit,
342
- 'carbohydrate_grams': new_carbohydrate_grams,
343
- 'notes': new_notes
344
- }])
345
- food_data = pd.concat([food_data, new_row], ignore_index=True)
346
-
347
- # Save the updated food_data to the local CSV (or HF Dataset - implement that function)
348
- food_data.to_csv("food_data.csv", index=False) # Save locally
349
- print(f"Added {new_food_name} to the database and saved to food_data.csv")
350
-
351
- # Now try to get nutrition info again
352
- nutrition_info = get_food_nutrition(new_food_name, food_data, portion_size)
353
- if not nutrition_info:
354
- return (
355
- f"Added {new_food_name} to database, but still could not retrieve nutrition information. Verify data.",
356
- "No insulin calculations available",
357
- None,
358
- None,
359
- None
360
- )
361
- else:
362
- return (
363
- f"Could not find nutrition information for: {food_name}. Please add it using the 'Add New Food' tab and provide the data.", # User prompt
364
- "No insulin calculations available",
365
- None,
366
- None,
367
- None
368
- )
369
 
370
  # 2. Insulin Calculations
371
  try:
@@ -615,6 +650,8 @@ def compute_metrics(eval_pred):
615
 
616
  # # trainer.save_model("food_classifier") # save locally
617
  # # trainer.push_to_hub() # upload to HF Hub
618
- # app.launch(share=True)
 
619
  if __name__ == "__main__":
 
620
  app.launch(share=True)
 
30
  "18:00-24:00": 0.7
31
  }
32
 
33
+ # Global variable to store food name vocabulary
34
+ food_name_vocabulary = None
35
+
36
  # -------------------------------------------------
37
  # Load Food Data from Hugging Face Dataset
38
  # -------------------------------------------------
39
 
40
  def load_food_data(dataset_name="Anupam007/Diabetic", local_csv="food_data.csv"):
41
+ """Loads food data from Hugging Face Dataset or a local CSV."""
42
  try:
43
+ # Try loading from local CSV first
44
+ if os.path.exists(local_csv):
45
+ food_data = pd.read_csv(local_csv)
46
+ print(f"Loaded food data from local CSV: {local_csv}")
47
+ else:
48
+ # Load from Hugging Face Dataset
49
+ dataset = load_dataset(dataset_name)
50
+ food_data = dataset['train'].to_pandas()
51
+ print(f"Loaded food data from Hugging Face Dataset: {dataset_name}")
52
+
53
+ # Normalize column names to lowercase and remove spaces
54
+ food_data.columns = [col.lower().replace(' ', '') for col in food_data.columns]
55
+
56
+ # Remove unnamed columns
57
+ food_data = food_data.loc[:, ~food_data.columns.str.contains('^unnamed')]
58
+
59
+ # Normalize food_name column to lowercase: Crucial for matching
60
+ if 'food_name' in food_data.columns:
61
+ food_data['food_name'] = food_data['food_name'].str.lower()
62
+ print("Unique Food Names in Dataset:")
63
+ print(food_data['food_name'].unique())
64
+ else:
65
+ print("Warning: 'food_name' column not found in dataset.")
66
+ food_data = pd.DataFrame({
67
+ 'food_category': ['starch'],
68
+ 'food_subcategory': ['bread'],
69
+ 'food_name': ['white bread'], # lowercase default
70
+ 'serving_description': ['servingsize'],
71
+ 'serving_amount': [29],
72
+ 'serving_unit': ['g'],
73
+ 'carbohydrate_grams': [15],
74
+ 'notes': ['default']
75
+ })
76
+
77
+ #Print first 5 rows to check columns and values
78
+ print("First 5 rows of loaded data:")
79
+ print(food_data.head())
80
+
81
  return food_data
82
 
83
  except Exception as e:
84
  print(f"Error loading data: {e}")
85
  # Provide minimal default data in case of error
86
  food_data = pd.DataFrame({
87
+ 'food_category': ['starch'],
88
+ 'food_subcategory': ['bread'],
89
+ 'food_name': ['white bread'], # lowercase default
90
+ 'serving_description': ['servingsize'],
91
+ 'serving_amount': [29],
92
+ 'serving_unit': ['g'],
93
+ 'carbohydrate_grams': [15],
94
  'notes': ['default']
95
  })
96
  return food_data
 
113
  processor = None
114
  model = None
115
 
116
+ def load_food_name_vocabulary(dataset_name="Anupam007/Diabetic"):
117
+ """Loads the food name vocabulary from the dataset."""
118
+ global food_name_vocabulary # Use global keyword to modify the global variable
119
+ try:
120
+ dataset = load_dataset(dataset_name)
121
+ food_data = dataset['train'].to_pandas()
122
+ food_data['food_name'] = food_data['food_name'].str.lower()
123
+ food_name_vocabulary = food_data['food_name'].unique().tolist()
124
+ print("Food name vocabulary loaded.")
125
+ return food_name_vocabulary
126
+
127
+ except Exception as e:
128
+ print(f"Error loading food name vocabulary: {e}")
129
+ food_name_vocabulary = [] # Initialize to empty list in case of error
130
+ return food_name_vocabulary
131
+
132
  def classify_food(image):
133
+ """Classify food image using the pre-trained model, only return names from the allowed vocabulary."""
134
+ global food_name_vocabulary # Access global vocabulary
135
+
136
+ if food_name_vocabulary is None:
137
+ load_food_name_vocabulary() # Load vocab if not already loaded
138
+
139
  try:
140
  if not model_loaded:
141
+ print("Model not loaded, returning None")
142
+ return None
 
 
143
 
144
  if isinstance(image, np.ndarray):
 
145
  image = Image.fromarray(image)
146
 
 
 
147
  image = processor(images=image, return_tensors="pt")
 
148
 
149
  with torch.no_grad():
150
  outputs = model(**image)
151
  predicted_idx = torch.argmax(outputs.logits, dim=-1).item()
152
+ predicted_food_name = model.config.id2label.get(predicted_idx, None) # Get the predicted name OR None if not available
153
+
154
+ if predicted_food_name and predicted_food_name.lower() in food_name_vocabulary:
155
+ print(f"Predicted food name: {predicted_food_name.lower()}")
156
+ return predicted_food_name.lower()
157
+ else:
158
+ print(f"Predicted food name {predicted_food_name} not in dataset vocabulary.")
159
+ return None # Or some other special value like "unknown_food"
160
 
161
  except Exception as e:
162
+ print(f"Classify food error: {e}")
163
+ return None
164
 
165
 
166
  def get_food_nutrition(food_name: str, food_data, portion_size: float = 1.0) -> Optional[Dict[str, Any]]:
167
  """Get carbohydrate content for the given food""" #No USDA anymore
168
+ if food_name is None: #If food is none, immediately return None to avoid an error.
169
+ return None
170
  try:
171
  # First try the local CSV database
172
  food_name_lower = food_name.lower() # Ensure input is also lowercase
 
381
 
382
  # 1. Food Classification and Carb Calculation
383
  food_name = classify_food(food_image) # This line is now inside the function
384
+
385
+ if food_name is None:
386
+ return (
387
+ "Food not recognized. Please choose a different image, or add this item to your dataset.",
388
+ "No insulin calculations available",
389
+ None,
390
+ None,
391
+ None
392
+ )
393
+
394
  print(f"Classified food name: {food_name}") # Debugging: What is classified as? # Corrected indentation
395
  nutrition_info = get_food_nutrition(food_name, food_data, portion_size) # Changed to pass in data
396
  if not nutrition_info:
397
+ return (
398
+ f"Could not find nutrition information for: {food_name} in the local database", # Removed USDA ref
399
+ "No insulin calculations available",
400
+ None,
401
+ None,
402
+ None
403
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
 
405
  # 2. Insulin Calculations
406
  try:
 
650
 
651
  # # trainer.save_model("food_classifier") # save locally
652
  # # trainer.push_to_hub() # upload to HF Hub
653
+
654
+ # before app launch, load food name vocabulary
655
  if __name__ == "__main__":
656
+ load_food_name_vocabulary()
657
  app.launch(share=True)