Source code for orgmatt.metabolism.nutrient_flows

# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2022-2023 Tanguy Fardet
# SPDX-License-Identifier: GPL-3.0-or-later
# orgmatt/metabolism/nutrient_flows.py

import re

from typing import Literal, Optional

import numpy as np

from .._utils import auto_format, return_values
from .._utils.tools import _filter_dataframe, _group_from_age, _regex_age
from ..data import body_compo, nutrients_flow_fractions
from ..typing import NumericArrayLike, NumericOrArray


r20_24 = re.compile(_regex_age("20-24"))
r25_29 = re.compile(_regex_age("25-29"))
r20_29 = re.compile(_regex_age("20-29"))


[docs] @auto_format def body_composition( nutrient: str, ci: int = 0, q: Optional[NumericArrayLike] = None, **kwargs ) -> NumericOrArray: ''' Fraction of the body mass represented by `nutrient`. Parameters ---------- nutrient : str Name of the nutrient (among "N", "P", "K", "Ca"). ci : int (optional, default: 0) Confidence interval (CI). If non-zero, the function will also return the low and high expected values corresponding to that CI. q : array-like of floats (optional: default: None) Percentiles to compute (supersedes `ci`). kwargs : dict, optional Additional arguments to constrain the result, e.g. "age", "group", "sex", or "region". Returns ------- A float in [0, 1) giving the fraction of body mass made of `nutrient`. ''' filters = kwargs.copy() filters["compound"] = nutrient df = _filter_dataframe(body_compo, filters) return 0.01*return_values(df, "content", 1, ci_value=ci, q=q)
[docs] @auto_format def fraction_nutrient_retention( nutrient: str, ci: int = 0, q: Optional[NumericArrayLike] = None, **kwargs ) -> NumericOrArray: ''' Fraction of a nutrient retained in the body during growth. Parameters ---------- nutrient : str The nutrient of interest. ci : int (optional, default: 0) Confidence interval (CI). If non-zero, the function will also return the low and high expected values corresponding to that CI. q : array-like of floats (optional: default: None) Percentiles to compute (supersedes `ci`). **kwargs : arguments to use a subset of the database Additional arguments can be use to restrict the results to a subset of the full database. E.g. one can specify an `age` or a `group`. Returns ------- A float in [0, 1) giving the fraction of the daily nutrient intake retained in the body. ''' group = kwargs.get("group", "") age = kwargs.get("age") if not group and age: group = _group_from_age(age) if group == "senior": return 0. elif "adult" in group: if age and nutrient == "P": # check for phosphorus in young adults if r20_24.match(age): return 0.01 elif r25_29.match(age): return 0.005 elif r20_29.match(age): return 0.0075 if "young" not in group: return 0. if "young" not in group: return 0. # return proper values for kids and young adults filters = kwargs.copy() filters["compound"] = nutrient filters["flow"] = "retention" df = _filter_dataframe(nutrients_flow_fractions, filters) frac = 0.01*return_values(df, "amount", 1, ci_value=ci, q=q) if np.isnan(frac).any() and "age" in filters: del filters["age"] filters["group"] = group df = _filter_dataframe(nutrients_flow_fractions, filters) frac = 0.01*return_values(df, "amount", 1, ci_value=ci, q=q) return frac
[docs] @auto_format def fraction_nutrient_excreta( nutrient: str, excreta: Literal["urine", "feces", "all"] = "all", ci: int = 0, q: Optional[NumericArrayLike] = None, **kwargs ) -> NumericOrArray: r''' Fraction of the ingested nutrients that is excreted in urine and feces. Other pathways notably include sweat, breathing, tegumen losses, and retention in bones and muscles before adulthood. .. math:: f_{\text{excreta}}^{(n)} = 1 - f_{\text{other losses}}^{(n)} - f_{\text{retention}}^{(n)} Parameters ---------- nutrient : str The nutrient of interest. ci : int (optional, default: 0) Confidence interval (CI). If non-zero, the function will also return the low and high expected values corresponding to that CI. q : array-like of floats (optional: default: None) Percentiles to compute (supersedes `ci`). **kwargs : arguments to use a subset of the database Additional arguments can be use to restrict the results to a subset of the full database. E.g. one can specify an `age` or a `group`. Returns ------- A float in [0, 1) giving the fraction of the daily nutrient intake that ends up in excreta (urine and feces combined). ''' if excreta == "all": frac: NumericOrArray = 1. if nutrient == "K": # approximately 20% loss in sweat frac = 0.8 elif nutrient == "N": # tegumen, sweat, and breathing losses frac = 0.95 # subtract retention from bone and muscle accumulation frac -= fraction_nutrient_retention(nutrient, ci=ci, q=q, **kwargs) return frac group = kwargs.get("group", "") age = kwargs.get("age") if not group and age: group = _group_from_age(age) # return proper values for kids and young adults filters = kwargs.copy() filters["compound"] = nutrient filters["flow"] = excreta df = _filter_dataframe(nutrients_flow_fractions, filters) frac = 0.01*return_values(df, "amount", 1, ci, q) if np.isnan(frac).any() and "age" in filters: del filters["age"] filters["group"] = group df = _filter_dataframe(nutrients_flow_fractions, filters) frac = 0.01*return_values(df, "amount", 1, ci, q) return frac