Units of Measurement & User Preferred Measurements

Adapt measures to user preferences (metric/imperial, cooking measures, portions) while keeping grams as the source of truth.

What You’ll Build

You’ll implement a measurement-aware intake flow that adapts units to each user’s preferences at both dish and ingredient level. Your app will retrieve the available units (weight and cooking measures, plus portion sizes), determine which ones apply to specific dishes/ingredients (respecting solid vs liquid), and display them in the user’s preferred system. When users select a unit (e.g., cups, teaspoons, slices) or a portion size (e.g., 1/2, 1/4), the app converts to grams for submission to the API and for consistent recalculation of ingredients and nutrition.

This addresses the complexity of regional systems (metric vs imperial) and culinary language (cooking measures) while maintaining precision, ensuring a smooth UX for end users and predictable data for developers.


Prerequisites

  • Plan: Monitor and above (see more info about LogMeal Plans)
  • User type: 🔴 APIUser (see more info about User Types)
  • Client library for HTTP (e.g., Python requests, Node axios, Java OkHttp).
  • 1–2 sample food images (JPEG/PNG) or a saved intake to test measures at dish and ingredient level.

Sequence Diagrams

sequenceDiagram
  participant User
  participant App
  participant LogMeal API

  User->>App: Capture/choose meal photo or open existing intake
  App->>LogMeal API: POST /v2/image/segmentation/complete <br> (Authorization: 🔴 **APIUser** token, image)
  LogMeal API-->>App: 200 OK (imageId, segmentation results)
  App-->>User: Show top dish candidates per detected item
  User->>App: Confirm/adjust dish per item
  App->>LogMeal API: POST /v2/image/confirm/dish (imageId, confirmed items)
  LogMeal API-->>App: 200 OK (confirmed items)

  Note over App,LogMeal API: Load available measurements
  App->>LogMeal API: GET /v2/dataset/weightMeasures/dishes
  LogMeal API-->>App: 200 OK (dish-level weight + cooking measures)
  App->>LogMeal API: GET /v2/dataset/weightMeasures/ingredients
  LogMeal API-->>App: 200 OK (ingredient-level weight + cooking measures)

  Note over App,LogMeal API: Resolve applicable cooking measures per item
  App->>LogMeal API: GET /v2/dataset/dishes?cooking_measures
  LogMeal API-->>App: 200 OK (dish.cooking_measures IDs)
  App->>LogMeal API: GET /v2/dataset/ingredients?cooking_measures
  LogMeal API-->>App: 200 OK (ingredient.cooking_measures IDs)

  App-->>User: Display measures by item (solid/liquid aware) in preferred system
  User->>App: Select units/amounts (e.g., 1 cup, 2 slices, portions like 1/2 apply to dishes only)
  App-->>App: Convert to grams using grams_conversion

  opt Quantity confirmation (optional)
    App->>LogMeal API: POST /v2/nutrition/confirm/quantity (imageId, per-item grams + optional measures)
    LogMeal API-->>App: 200 OK (updated quantities)
  end

  App->>LogMeal API: GET /v2/intake/{imageId}
  LogMeal API-->>App: 200 OK (dishes, ingredients, nutrition with measures and weights)
  App-->>User: Display standardized measures + recalculated quantities

Implementation Guide

Implementation Examples

Understanding the measurement systems

  • 1) Basic Weight Measurements: precise, global; metric (e.g., grams, milliliters) and imperial (e.g., ounce, pound, teaspoon). Valid for dishes and ingredients; each unit carries state (solid/liquid) and type (metric/imperial).
  • 2) Cooking Measurements: user-friendly, less precise; split into ingredient-specific (e.g., teaspoon, drop, slice) and dish-specific (e.g., glass, cup, fillet). Applicability is item-dependent—e.g., “slice” applies to cheese but not to water.
  • 3) Portion Size: broad, dish-level amounts (e.g., 1/2, 1/4) that apply to dishes (high level), not to ingredients (low level).

Dish vs Ingredient scope

  • High level (dishes/food items): e.g., cheesecake, pizza, sushi.
  • Low level (ingredients): e.g., cheese, beef, pepperoni, salmon.
    Cooking measures availability and solid vs liquid constraints differ per item and are discoverable via dataset endpoints.

Retrieving available measurements

  • Dish level: GET /dataset/weightMeasures/dishes → returns weight and cooking_measures for dishes; each weight unit includes state (solid/liquid) and type (metric/imperial).
  • Ingredient level: GET /dataset/weightMeasures/ingredients → returns weight and cooking_measures for ingredients; each weight unit includes state and type. Also note that GET /dataset/ingredients returns a state attribute (solid/liquid) for each ingredient, which you should use to filter applicable measurements.

Linking cooking measures to specific items

  • Dish level: GET /dataset/dishes with ?cooking_measures to receive cooking_measures IDs for each dish; match them to IDs from dish-level weightMeasures.
  • Ingredient level: GET /dataset/ingredients with ?cooking_measures to receive cooking_measures IDs for each ingredient; match them to IDs from ingredient-level weightMeasures.
  • Item state (solid/liquid) is also exposed under each dish’s measure attribute when you retrieve intake details (see below).

Retrieving intake measures/weights

  • Ingredients per intake: POST /nutrition/recipe/ingredients → returns recipe_per_item; each dish contains measure (dish-level measures & weight). Inside recipe, each ingredient includes its specific measures/weights.
  • Full intake details: GET /intake/{imageId} → returns dishes, ingredients, nutrition, and detailed measures/weights for each entity.

User preferred measurements

Units conversion & quantity confirmation

  • Grams are the common denominator: every weight/cooking/portion unit provides a grams_conversion.
  • Convert user-entered amounts to grams client-side before calling write endpoints.
  • Example: 2 ounces × the unit’s grams_conversion (28.34375) → 56.69 g (2 decimals is sufficient).

Related Code Examples (Recipes)

User Interaction Recommendations

  • Let users toggle Metric / Imperial / Cooking per item, honoring global preferences from the profile.
  • Show only applicable cooking measures for each item (respecting solid/liquid).
  • Prefer grams as an internal canonical unit; display chosen units in the UI.
  • Surface grams_conversion inline when users type amounts for transparency.
  • For portions (dish-level only), offer 1/4, 1/2, 3/4, 1 with quick actions and allow custom entry.

Related Endpoints


Common Pitfalls & Tips

  • Don’t show cooking measures that are inapplicable to a given item (e.g., “slice” for liquids). Always filter by item and state.
  • Keep grams as the only write-time unit; convert from the user’s visible unit using grams_conversion.
  • Respect user preferred systems at both dish and ingredient levels; provide easy overrides per item.
  • Localize labels and abbreviations (e.g., “oz”, “cup”) according to the selected system and user profile.
  • When reading an intake, inspect recipe_per_itemmeasure and ingredient recipe blocks for accurate display.

Name collisions across contexts (important) Some labels (e.g., “cup”) can exist in multiple measurement systems or semantic levels with different IDs and grams_conversion. For example:

  • “cups” as an imperial liquid measure ≈ 240 g,
  • “cups” as dish cooking measures with id=2 (≈240 g) used by dishes like “tea” (id 1308) or “hot chocolate” (id 2642),
  • “cups” again as dish cooking measures with id=14 (≈170 g) for dishes like “irish coffee” (id 2653) or “coffee” (id 1291).

Always match by ID, not just by name, and use the provided grams_conversion.


Optional Enhancements

  • Add portion presets (1/4, 1/2, 3/4, 1) next to cooking measures for dishes.
  • Provide unit search and recent favorites for commonly used measures.
  • Offer a nutrition preview that updates live as the unit or amount changes.
  • Educate users with lightweight tooltips on metric vs imperial differences.

Next Steps