Source code for orgmatt.nutrients.all_nutrients

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

from typing import Optional, Union, cast

import numpy as np
from pint import Quantity

from .._utils import _filter_dataframe, return_values, auto_format
from ..agrifood import nutrient_intake
from ..data import excr_content, food, nutrients_excr
from ..metabolism import fraction_nutrient_excreta
from ..typing import NumericArrayLike, NumericOrArray
from ..units import ureg, check_dim


__all__ = [
    "nutrient_from_biowaste",
    "nutrient_from_compound",
    "nutrient_from_population",
]


[docs] @auto_format @check_dim(arglist=('duration', 1, '[time]'), result='[mass]*[X]') def nutrient_from_population( pop: NumericOrArray, duration: Quantity, nutrient: str, excreta: str = "all", ci: int = 0, q: Optional[NumericArrayLike] = None, **kwargs ) -> Quantity: ''' Compute the amount of a nutrient generated by a given population over a certain duration using the ``nutrients_intake.csv`` or ``nutrients_excreted.csv`` database. .. warning :: Current results only work for adults, results for children and adolescents will be (strongly) overestimated. Parameters ---------- pop : float or numpy array Number of inhabitants. duration : float [time] Time interval over which the nitrogen is excreted. nutrient : str Chemical symbol for the nutrient (among 'N', 'P', 'K', 'Mg', 'Ca') excreta : str (optional, default: "all") Type of excreta ("urine", "feces", or "all"). 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 add `sex="male"` to return only nitrogen excretion from male subjects, or `region="South Asia"` to use only values obtained from studies in South Asian countries. Returns ------- nutrient_mass : float or array of dimension D [mass]*[nutrient] Mean mass of excreted nitrogen if `q` is None or `ci` is 0. If `q` is provided, returns the values associated to each percentile in `q` for each entry in `pop`; otherwise one (low, mean, high) result per entry in `pop`, giving the masses expected for the requested confidence interval. The dimension D is either 3, len(q), (len(pop), 3), or (len(pop), len(q)) depending on `ci` and `q`. ''' if excreta.lower() == "all": # account for nutrient pathways besides exretions factor = fraction_nutrient_excreta(nutrient, **kwargs) return factor * nutrient_intake( pop, duration, nutrient, ci=ci, **kwargs) df = nutrients_excr[nutrients_excr.compound == nutrient] unit = df.iloc[0].unit df = _filter_dataframe(df, kwargs) if excreta.lower() == "urine": res = return_values(df[df.flow == "urine"], "amount", pop, ci, q) else: res = return_values(df[df.flow == "feces"], "amount", pop, ci, q) return ureg(unit) * duration * res
[docs] @auto_format(default_group=None) @check_dim(arglist=('mass', 0, '[mass]'), result='[mass]*[X]') def nutrient_from_biowaste( mass: Quantity, nutrient: str, waste_type: str = "BiodegradableWaste", ci: int = 0, q: Optional[NumericArrayLike] = None, **kwargs ) -> Quantity: ''' Compute the amount of a nutrient contained in biowaste (food residues, i.e. kitchen and food waste, by default) using the ``food.csv`` database. Parameters ---------- mass : pint.Quantity [mass] Mass of biowaste. nutrient : str Chemical symbol for the nutrient (among 'N', 'P', 'K') waste_type : str (optional, default: "BiodegradableWaste") Type of biowaste, among "BiodegradableWaste" for all household biowaste, including some paper; cardboard, compostable plastics, and some green waste, "GreenWaste", for plants and garden wastes, "FoodWaste", for all unconsumed edible food, "KitchenWaste" (peels, bones...), and "FoodResidues", which includes food and kitchen waste. 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 add `region="Europe"` to use only values obtained from studies in European countries. Returns ------- nutrient_mass : float or array of dimension D [mass]*[nutrient] Mean mass of excreted nutrient if `q` is None or `ci` is 0. If `q` is provided, returns the values associated to each percentile in `q` for each entry in `amount`; otherwise one (low, mean, high) result per entry in `amount`, giving the masses expected for the requested confidence interval. The dimension D is either 3, len(q), (len(amount), 3), or (len(amount), len(q)) depending on `ci` and `q`. ''' assert nutrient in ("TOC", "N", "P", "K"), \ "`nutrient` must be either 'N', 'P', 'K', or 'TOC'." df = food[ (food.property == nutrient) & (food.type == _bw[waste_type]) ] unit = df.iloc[0].unit # remove potential duplicate entry for type vs waste_type argument kwargs = kwargs.copy() if "type" in kwargs: del kwargs["type"] df = _filter_dataframe(df, kwargs) return ureg(unit) * return_values(df, "value", mass, ci, q)
[docs] @auto_format @check_dim(arglist=('amount', 0, '[length]**3|[mass]'), result='[mass]*[X]') def nutrient_from_compound( amount: Quantity, nutrient: str, compound_type: str, ci: int = 0, q: Optional[NumericArrayLike] = None, **kwargs ) -> Quantity: ''' Compute the amount of nutrients contained in a specific compound. Parameters ---------- amount: pint.Quantity Amount of compound. nutrient: str Type of nutrient to return. compound_type: str Type of compound among "urine", "feces" = "feces (wet)", "feces (dry)", "biowate" = "BiodegradableWaste", "food residues" = "FoodResidues", "food waste" = "FoodWaste". 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 add `region="Europe"` to use only values obtained from studies in European countries. Returns ------- nutrient_mass : float or array of dimension D [mass]*[nutrient] Mean mass of excreted nutrient if `q` is None or `ci` is 0. If `q` is provided, returns the values associated to each percentile in `q` for each entry in `amount`; otherwise one (low, mean, high) result per entry in `amount`, giving the masses expected for the requested confidence interval. The dimension D is either 3, len(q), (len(amount), 3), or (len(amount), len(q)) depending on `ci` and `q`. ''' assert compound_type in _valid_compounds, \ f"Invalid `compound_type`: {compound_type}." kwargs = kwargs.copy() if compound_type in _bw: if "group" in kwargs: del kwargs["group"] return nutrient_from_biowaste( amount, nutrient, waste_type=_bw[compound_type], ci=ci, **kwargs) ct = _excr.get(compound_type, compound_type) df = excr_content[ (excr_content.compound == nutrient) & (excr_content.excreta == ct) ] if df.empty: return np.NaN*ureg(f"g{nutrient}") unit = df.iloc[0].unit for k, v in kwargs.items(): assert k in df, f"Unknown database entry '{k}'." df = df[df[k] == v] # compute nutrient mass nutrient_content = return_values(df, "content", amount, ci, q) return ureg(unit) * nutrient_content
# argument conversion _bw = { "biowaste": "BiodegradableWaste", "BiodegradableWaste": "BiodegradableWaste", "food": "FoodResidues", "FoodResidues": "FoodResidues", "food waste": "FoodWaste", "FoodWaste": "FoodWaste" } _excr = {"feces": "feces (wet)"} _valid_compounds = set(_bw).union( tuple(_bw.values()) + ("feces", "feces (wet)", "feces (dry)", "urine") )