GFM VitaScore
Le Gap Filling Module VitaScore calcule les incidences sur la santé humaine des produits alimentaires basées sur les facteurs de risque alimentaire de l'étude Charge mondiale de morbidité (Global Burden of Disease - GBD). Il convertit la composition alimentaire en années de vie corrigées de l'incapacité (AVCI, ou DALYs en anglais), permettant des comparaisons d'incidence sur la santé parallèlement aux métriques environnementales.
Référence rapide
| Propriété | Description |
|---|---|
| S'exécute sur | FoodProductFlowNode |
| Dépendances | AggregationGapFillingWorker, DailyFoodUnitGapFillingWorker |
| Entrée clé | Quantités par catégorie alimentaire, valeurs nutritionnelles, unité alimentaire quotidienne |
| Sortie | VitaScore en DALYs par facteur de risque alimentaire |
| Déclencheur | Le produit dispose de catégories alimentaires agrégées et d'une unité alimentaire quotidienne |
Conditions d'exécution
Le module se déclenche lorsque :
- L'agrégation des catégories alimentaires est terminée
- Le calcul de l'unité alimentaire quotidienne (DFU) est terminé
- Le noeud dispose de données
amount_per_category_in_flowvalides - Le noeud dispose d'une valeur
daily_food_unitvalide
Sortie clé
Le module produit :
- VitaScore total : Incidence sur la santé agrégée en DALYs
- Scores par facteur : Contributions individuelles en DALYs de chaque facteur de risque alimentaire
- Versions actuelle et héritée : Deux méthodes de calcul pour comparaison
Méthodologie scientifique
Le VitaScore quantifie l'incidence sur la santé de la consommation alimentaire en utilisant les années de vie corrigées de l'incapacité (DALYs) basées sur l'étude Charge mondiale de morbidité. Un DALY représente la perte d'une année de pleine santé.
Cadre de la Charge mondiale de morbidité
L'étude GBD identifie les facteurs de risque alimentaire contribuant à la charge de morbidité. Le VitaScore utilise 13 facteurs de risque regroupés en deux catégories :
Facteurs de risque positifs (une consommation plus élevée est bénéfique) :
- Régime pauvre en fruits
- Régime pauvre en légumes
- Régime pauvre en céréales complètes
- Régime pauvre en noix et graines
- Régime pauvre en lait
Facteurs de risque négatifs (une consommation plus élevée est nocive) :
- Régime riche en sodium
- Régime riche en viande transformée
- Régime riche en viande rouge
- Régime riche en énergie
- Régime riche en lipides
- Régime pauvre en lipides
- Régime riche en protéines
- Régime pauvre en protéines
Niveau d'exposition à risque théorique minimum (TMREL)
Chaque facteur de risque alimentaire a une plage de consommation optimale appelée TMREL - le niveau d'exposition qui minimise le risque pour la santé. Le VitaScore calcule l'écart entre la consommation réelle et cette plage optimale.
Le TMREL est défini par deux bornes :
- t_1 : Borne inférieure de la plage optimale
- t_2 : Borne supérieure de la plage optimale
La formule VitaScore
La formule centrale calcule une fraction de risque (f_r) pour chaque facteur de risque alimentaire, puis multiplie par la charge de DALYs associée :
Pour les facteurs positifs (où consommer plus est mieux) :
f_r = (t_2 / (t_2 - t_1)) - x_r / (scaling * (t_2 - t_1))
Pour les facteurs négatifs (où consommer moins est mieux) :
f_r = x_r / (scaling * (t_2 - t_1)) - (t_1 / (t_2 - t_1))
Où :
- x_r : Quantité du facteur de risque dans le produit alimentaire
- t_1, t_2 : Bornes inférieure et supérieure du TMREL
- scaling : Facteur de normalisation (voir ci-dessous)
- f_r : Fraction de risque (limitée à la plage 0-1)
Calcul final :
VitaScore[r] = DALY_r * f_r
VitaScore total = somme(VitaScore[r] pour tous les facteurs de risque)
Méthodes de normalisation
Le VitaScore prend en charge trois méthodes de normalisation pour différents facteurs de risque :
| Méthode | Description | Utilisation |
|---|---|---|
| per_dfu | Mise à l'échelle par unité alimentaire quotidienne | La plupart des facteurs de risque (fruits, légumes, viande, etc.) |
| per_total_energy | Mise à l'échelle par contenu énergétique total | Lipides et protéines en pourcentage des calories |
| per_self | Pas de mise à l'échelle (facteur = 1,0) | Mesures directes |
Unité alimentaire quotidienne (DFU)
L'unité alimentaire quotidienne représente la quantité de consommation quotidienne typique d'une catégorie alimentaire. Elle normalise le calcul de sorte que l'incidence sur la santé d'un aliment soit proportionnelle à la part qu'il représente dans le régime quotidien.
Détails d'implémentation
Facteurs de risque alimentaire couverts
Le module calcule les incidences sur la santé pour 13 facteurs de risque alimentaire. Chaque facteur a un niveau d'exposition à risque théorique minimum (TMREL) définissant la plage de consommation optimale.
Facteurs de risque positifs (une consommation plus élevée est bénéfique)
| Facteur de risque | TMREL inférieur | TMREL supérieur | Unité | Normalisation | DALY | Référence de recommandation alimentaire |
|---|---|---|---|---|---|---|
| Régime pauvre en fruits | 200 | 300 | g/jour | per_dfu | 61,24 | L'OMS recommande ≥400 g/jour fruits et légumes combinés1 |
| Régime pauvre en légumes | 340 | 500 | g/jour | per_dfu | 30,57 | L'OMS recommande ≥400 g/jour fruits et légumes combinés1 |
| Régime pauvre en céréales complètes | 100 | 150 | g/jour | per_dfu | 82,86 | Recommandations américaines : 3-4 portions/jour (~48-64 g)2 |
| Régime pauvre en noix et graines | 16 | 25 | g/jour | per_dfu | 13,98 | EAT-Lancet : ~50 g/jour de noix3 |
| Régime pauvre en lait | 350 | 520 | g/jour | per_dfu | 9,42 | 2-3 portions de produits laitiers/jour (~400-600 ml)4 |
Facteurs de risque négatifs (une consommation plus élevée est nocive)
| Facteur de risque | TMREL inférieur | TMREL supérieur | Unité | Normalisation | DALY | Référence de recommandation alimentaire |
|---|---|---|---|---|---|---|
| Régime riche en sodium (sel) | 1 | 5 | g/jour | per_dfu | 29,43 | L'OMS recommande <5 g sel/jour (<2 g sodium)5 |
| Régime riche en viande transformée | 0 | 4 | g/jour | per_dfu | 96,94 | EAT-Lancet : éviter ou minimiser la viande transformée3 |
| Régime riche en viande rouge | 18 | 27 | g/jour | per_dfu | 74,25 | EAT-Lancet : ~14 g/jour (~100 g/semaine)3 |
Facteurs de risque des macronutriments (énergie et pourcentage de l'énergie totale)
| Facteur de risque | TMREL inférieur | TMREL supérieur | Unité | Normalisation | DALY | Référence de recommandation alimentaire |
|---|---|---|---|---|---|---|
| Régime riche en énergie | 650 | 1250 | kcal | per_self | 88,66 | Un repas équilibré : 450-850 kcal (~⅓ de 2200 kcal/jour)4 |
| Régime riche en lipides | 27,5 % | 50 % | % de kcal | per_total_energy | 88,66 | Recommandations EFSA/américaines : 20-35 % d'énergie des lipides46 |
| Régime pauvre en lipides | 5 % | 27,5 % | % de kcal | per_total_energy | 88,66 | Recommandations EFSA/américaines : 20-35 % d'énergie des lipides46 |
| Régime riche en protéines | 22,5 % | 60 % | % de kcal | per_total_energy | 88,66 | AMDR américain : 10-35 % d'énergie des protéines6 |
| Régime pauvre en protéines | 0 % | 22,5 % | % de kcal | per_total_energy | 88,66 | AMDR américain : 10-35 % d'énergie des protéines6 |
Les valeurs DALY sont exprimées en DALYs pour 100 000 personnes-années et représentent la charge de morbidité attribuable à chaque facteur de risque alimentaire.
Conversion sodium en sel
Comme les recommandations alimentaires font souvent référence au sel (chlorure de sodium) plutôt qu'au sodium, le module convertit les valeurs de sodium :
# Le sodium représente environ 39,3 % du sel en masse
NA_PERCENT_IN_NACL = 39.337 # %
# Convertir le sodium en équivalent sel
salt_quantity = sodium_quantity * (100 / NA_PERCENT_IN_NACL)
Conversion énergétique des macronutriments
Les lipides et les protéines sont convertis de la masse en énergie pour les calculs de pourcentage de calories :
FAT_CALORIES_PER_GRAM = 9.0 # kcal/g
PROTEIN_CALORIES_PER_GRAM = 4.0 # kcal/g
fat_kcal = fat_grams * FAT_CALORIES_PER_GRAM
protein_kcal = protein_grams * PROTEIN_CALORIES_PER_GRAM
Support des versions
Le module maintient deux versions de calcul :
| Version | Description |
|---|---|
| current | Dernières valeurs DALY GBD 2021 |
| legacy | Valeurs DALY originales pour la rétrocompatibilité |
Les deux versions sont calculées et stockées, permettant la comparaison des résultats entre les mises à jour méthodologiques.
Référence complète du code
Flux de calcul principal
async def run(self, calc_graph: CalcGraph) -> None:
"""Effectuer le calcul du vitascore."""
# Obtenir les catégories alimentaires agrégées et l'unité alimentaire quotidienne
amount_per_category_in_flow_prop = self.node.amount_per_category_in_flow
dfu_prop = self.node.daily_food_unit
# Ajouter les facteurs de risque dérivés du sel et de la nutrition
salt_qty, energy_qty, fat_qty, protein_qty = (
self.retrieve_salt_and_nutrition_amounts_for_activity_production_amount()
)
# Calculer le vitascore pour les deux versions
for version in (VitascoreVersionEnum.legacy, VitascoreVersionEnum.current):
vitascore_for_local = self.compute_vitascore(
amount_per_category_in_flow_prop,
dfu_prop,
version,
ReferenceAmountEnum.amount_for_activity_production_amount,
)
# ... stocker les résultats
Implémentation de la formule VitaScore centrale
def vitascore_formula(
self,
food_category: QuantityPackageProp,
dfu: float,
legacy_or_current: str,
for_reference_amount: ReferenceAmountEnum,
) -> dict[UuidStr, ReferencelessQuantityProp]:
"""Formule de calcul du vitascore."""
vitascore = {
self.gfm_factory.vitascore_term.uid: ReferencelessQuantityProp(
value=0.0, unit_term_uid=self.gfm_factory.daly_unit_term.uid
)
}
for idx, term in enumerate(
self.gfm_factory.positive_terms + self.gfm_factory.negative_terms
):
if term.xid in self.gfm_factory.used_categories_xid:
# Obtenir les bornes TMREL depuis les données du terme
t_1 = float(term.data.get("tmrel").get("lower"))
t_2 = float(term.data.get("tmrel").get("upper"))
normalization = TmrelNormalizationEnum(
term.data.get("tmrel").get("tmrel_normalization")
)
# Obtenir la quantité depuis les catégories alimentaires
if term.uid in amount_per_category_in_flow_present:
x_r = float(amount_per_category_in_flow_present[term.uid].value)
else:
x_r = 0.0
# Obtenir la charge DALY pour ce facteur de risque
daly_r = float(term.data.get(legacy_or_current).get("amount"))
# Déterminer le facteur de mise à l'échelle
if normalization == TmrelNormalizationEnum.per_dfu:
scaling = dfu
elif normalization == TmrelNormalizationEnum.per_total_energy:
scaling = energy_kcal_value
elif normalization == TmrelNormalizationEnum.per_self:
scaling = 1.0
# Calculer la fraction de risque
if scaling <= 0.0:
f_r = 0.0
else:
if idx < len(self.gfm_factory.positive_terms):
# Facteurs positifs : plus c'est mieux
f_r = (t_2 / (t_2 - t_1)) - x_r / (scaling * (t_2 - t_1))
else:
# Facteurs négatifs : moins c'est mieux
f_r = x_r / (scaling * (t_2 - t_1)) - (t_1 / (t_2 - t_1))
# Limiter la fraction de risque à [0, 1]
f_r = max(0, min(1, f_r))
# Calculer et accumuler le vitascore
vitascore[term.uid] = ReferencelessQuantityProp(
value=daly_r * f_r,
unit_term_uid=self.gfm_factory.daly_unit_term.uid
)
vitascore[self.gfm_factory.vitascore_term.uid].value += daly_r * f_r
return vitascore
Récupération du sel et de la nutrition
def retrieve_salt_and_nutrition_amounts_for_activity_production_amount(
self,
) -> Tuple[Optional[ReferencelessQuantityProp], ...]:
"""Extraire les quantités de sel et de macronutriments depuis les données nutritionnelles."""
# Vérifier d'abord les nutriments agrégés, puis les valeurs nutritionnelles
if aggregated_nutrients := self.node.aggregated_nutrients:
nutrition_pkg = aggregated_nutrients.amount_for_activity_production_amount()
elif nutrient_values := self.node.nutrient_values:
nutrition_pkg = nutrient_values.amount_for_activity_production_amount()
# Gérer la séparation du chlorure de sodium
if nutrition_pkg and (sodium_chloride_term.uid in nutrition_pkg.quantities):
nutrition_pkg = split_sodium_chloride(nutrition_pkg)
# Convertir le sodium en sel
if sodium_term.uid in nutrition_pkg.quantities:
salt_qty = nutrition_pkg.quantities[sodium_term.uid].duplicate()
salt_qty.value *= 100 / NA_PERCENT_IN_NACL
# Obtenir l'énergie et convertir lipides/protéines en kcal
energy_kcal_qty = nutrition_pkg.quantities.get(energy_term.uid)
if fat_mass_qty := nutrition_pkg.quantities.get(fat_term.uid):
fat_in_grams = convert_to_grams(fat_mass_qty)
fat_qty = ReferencelessQuantityProp(
value=fat_in_grams * FAT_CALORIES_PER_GRAM,
unit_term_uid=kcal_term.uid
)
if protein_mass_qty := nutrition_pkg.quantities.get(protein_term.uid):
protein_in_grams = convert_to_grams(protein_mass_qty)
protein_qty = ReferencelessQuantityProp(
value=protein_in_grams * PROTEIN_CALORIES_PER_GRAM,
unit_term_uid=kcal_term.uid
)
return salt_qty, energy_kcal_qty, fat_qty, protein_qty
Exemple de calcul
Scénario : Calculer le VitaScore pour 100 g de jambon transformé
Étape 1 : Identifier les quantités de facteurs de risque
Depuis l'agrégation des catégories alimentaires :
- Viande transformée : 100 g
- Viande rouge : 0 g (comptée séparément de la viande transformée)
- Fruits : 0 g
- Légumes : 0 g
Depuis les valeurs nutritionnelles :
- Sodium : 1200 mg (converti en 3050 mg de sel)
- Énergie : 145 kcal
- Lipides : 8 g (72 kcal)
- Protéines : 18 g (72 kcal)
Étape 2 : Calculer les fractions de risque
Régime riche en viande transformée (facteur négatif) :
- TMREL : 0-0 g par jour (l'optimal est une consommation nulle)
- Mise à l'échelle : Unité alimentaire quotidienne (supposons 2000 g d'apport alimentaire quotidien)
- Quantité normalisée : 100 g / 2000 g = 0,05 (5 % de l'apport quotidien)
- Fraction de risque : Calculée selon l'écart au TMREL
Régime riche en sodium :
- TMREL : 1000-5000 mg par jour
- Quantité de sel : 3050 mg
- Fraction de risque : Basée sur où 3050 mg se situe dans la plage TMREL
Régime pauvre en fruits (facteur positif) :
- Quantité : 0 g
- Fraction de risque : Maximum (pas de contenu en fruits)
Étape 3 : Appliquer les valeurs DALY
Chaque fraction de risque est multipliée par la charge DALY associée depuis les données GBD :
- Charge DALY viande transformée : ~40 DALYs pour 100 000 personnes-années
- Charge DALY sodium : ~30 DALYs pour 100 000 personnes-années
Étape 4 : Additionner le VitaScore total
VitaScore total = somme de (DALY_r * f_r) pour les 13 facteurs de risque
Le résultat est exprimé en micro-DALYs par portion, représentant la charge de santé proportionnelle.
Sources de données
Étude Charge mondiale de morbidité
Le VitaScore est basé sur l'étude GBD 2021 :
GBD 2021 Risk Factors Collaborators (2024). Global burden and strength of evidence for 88 risk factors in 204 countries and 811 subnational locations, 1990-2021: a systematic analysis for the Global Burden of Disease Study 2021. The Lancet.
Données clés extraites :
- Charges DALY pour chaque facteur de risque alimentaire
- Plages TMREL pour une consommation optimale
- Estimations de risque relatif
Valeurs TMREL
Les niveaux d'exposition à risque théorique minimum proviennent de :
- Annexe 1 GBD 2021 : Spécifications détaillées du TMREL pour chaque facteur de risque
- Matériaux supplémentaires du Lancet : Données de support pour la dérivation du TMREL
Facteurs de médiation
Le GBD utilise des facteurs de médiation pour tenir compte des voies de risque qui se chevauchent. Par exemple, la viande rouge impacte la santé à la fois directement et par son effet sur l'indice de masse corporelle (IMC).
Limitations connues
Contraintes méthodologiques
- Moyennes de population : Les valeurs DALY représentent des moyennes mondiales ou régionales, pas des risques individuels
- Spécificité âge/sexe : L'implémentation actuelle utilise des valeurs à l'échelle de la population (des valeurs spécifiques âge/sexe sont disponibles mais non implémentées)
- Chevauchement des facteurs de risque : Les facteurs de médiation traitent partiellement mais pas totalement les risques corrélés
Limitations des données
- Correspondance alimentaire : Nécessite une classification précise des catégories alimentaires
- Complétude nutritionnelle : Les calculs sodium/lipides/protéines dépendent de données nutritionnelles complètes
- Incertitude TMREL : Les plages de consommation optimales comportent une incertitude scientifique inhérente
Lacunes de couverture
- Spécificité par pays : Les valeurs DALY peuvent être rendues spécifiques par pays mais utilisent actuellement des estimations mondiales
- Aliments transformés : Les aliments transformés complexes peuvent avoir une correspondance de catégorie incomplète
- Nouveaux aliments : Les nouvelles catégories alimentaires peuvent manquer d'associations établies avec les facteurs de risque
Références
-
GBD 2021 Risk Factors Collaborators (2024). Global burden and strength of evidence for 88 risk factors in 204 countries and 811 subnational locations, 1990-2021. The Lancet, 403(10440), 2162-2203.
-
Eaternity (2017). Documentation VitaScore. https://eaternity.org/assets/smart-chefs/2017-12-12_VitaScore_Documentation_web.pdf
-
Ernstoff, A., et al. (2020). Towards Win-Win Policies for Healthy and Sustainable Diets. Nutrients, 12(9), 2745.
-
Murray, C.J.L., et al. (2020). Global burden of 87 risk factors in 204 countries and territories, 1990-2019: a systematic analysis for the Global Burden of Disease Study 2019. The Lancet, 396(10258), 1223-1249.
-
Outil de résultats GBD. Institute for Health Metrics and Evaluation. https://vizhub.healthdata.org/