Source code for openalea.cnwheat.postprocessing

# -*- coding: latin-1 -*-

from __future__ import division  # use "//" to do integer division
import os

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from openalea.cnwheat import simulation as cnwheat_simulation, model as cnwheat_model, parameters as cnwheat_parameters, tools as cnwheat_tools
from openalea.respiwheat import model as respiwheat_model

"""
    cnwheat.postprocessing
    ~~~~~~~~~~~~~~~~~~~~~~

    The module :mod:`cnwheat.postprocessing` defines post-processing to apply
    on CN-Wheat outputs, and provides a front-end to automatize the generation of graphs
    for validation of the outputs.

    Please use front-ends :func:`postprocessing` and :func:`generate_graphs`.

"""

#: the time index
T_INDEX = cnwheat_simulation.Simulation.T_INDEX

#: the index to locate the plants in the modeled system
PLANTS_INDEXES = cnwheat_simulation.Simulation.PLANTS_INDEXES
#: concatenation of :attr:`T_INDEX` and :attr:`PLANTS_INDEXES`
PLANTS_T_INDEXES = cnwheat_simulation.Simulation.PLANTS_T_INDEXES
#: plants post-processing variables
PLANTS_POSTPROCESSING_VARIABLES = []
#: concatenation of :attr:`PLANTS_T_INDEXES`, :attr:`PLANTS_RUN_VARIABLES <cnwheat.simulation.Simulation.PLANTS_RUN_VARIABLES>` and :attr:`PLANTS_POSTPROCESSING_VARIABLES`
PLANTS_RUN_POSTPROCESSING_VARIABLES = set(PLANTS_T_INDEXES + cnwheat_simulation.Simulation.PLANTS_RUN_VARIABLES + PLANTS_POSTPROCESSING_VARIABLES)

#: the indexes to locate the axes in the modeled system
AXES_INDEXES = cnwheat_simulation.Simulation.AXES_INDEXES
#: concatenation of :attr:`T_INDEX` and :attr:`AXES_INDEXES`
AXES_T_INDEXES = cnwheat_simulation.Simulation.AXES_T_INDEXES
#: axes post-processing variables
AXES_POSTPROCESSING_VARIABLES = ['C_N_ratio', 'C_N_ratio_shoot', 'N_content', 'N_content_shoot', 'N_content_roots', 'N_content_mstruct', 'N_content_mstruct_shoot', 'N_content_total_DM_shoot',
                                 'N_content_mstruct_roots', 'sum_N_g', 'sum_N_g_shoot',
                                 'sum_dry_mass', 'sum_dry_mass_shoot', 'sum_dry_mass_laminae', 'sum_dry_mass_stem', 'sum_dry_mass_roots', 'dry_mass_phloem', 'shoot_roots_ratio',
                                 'shoot_roots_mstruct_ratio', 'Total_Photosynthesis', 'Tillers_Photosynthesis', 'Tillers_Photosynthesis_An', 'NNI',
                                 'NS', 'NS_shoot', 'NS_stem', 'NS_laminae', 'NS_roots', 'mstruct_shoot', 'mstruct_laminae', 'mstruct_stem',
                                 'C_respired_shoot', 'C_respired_roots', 'Cont_WSC_DM', 'Cont_WSC_DM_shoot', 'Cont_WSC_DM_roots', 'Cont_WSC_DM_laminae', 'Cont_WSC_DM_stem',
                                 'sum_C_g', 'sum_NSC_g']

#: concatenation of :attr:`AXES_T_INDEXES`, :attr:`AXES_RUN_VARIABLES <cnwheat.simulation.Simulation.AXES_RUN_VARIABLES>` and :attr:`AXES_POSTPROCESSING_VARIABLES`
AXES_RUN_POSTPROCESSING_VARIABLES = set(AXES_T_INDEXES + cnwheat_simulation.Simulation.AXES_RUN_VARIABLES + AXES_POSTPROCESSING_VARIABLES)

#: the indexes to locate the phytomers in the modeled system
PHYTOMERS_INDEXES = cnwheat_simulation.Simulation.PHYTOMERS_INDEXES
#: concatenation of :attr:`T_INDEX` and :attr:`PHYTOMERS_INDEXES`
PHYTOMERS_T_INDEXES = cnwheat_simulation.Simulation.PHYTOMERS_T_INDEXES
#: phytomers post-processing variables
PHYTOMERS_POSTPROCESSING_VARIABLES = []
#: concatenation of :attr:`PHYTOMERS_T_INDEXES`, :attr:`PHYTOMERS_RUN_VARIABLES <cnwheat.simulation.Simulation.PHYTOMERS_RUN_VARIABLES>` and :attr:`PHYTOMERS_POSTPROCESSING_VARIABLES`
PHYTOMERS_RUN_POSTPROCESSING_VARIABLES = set(PHYTOMERS_T_INDEXES + cnwheat_simulation.Simulation.PHYTOMERS_RUN_VARIABLES + PHYTOMERS_POSTPROCESSING_VARIABLES)

#: the indexes to locate the organs in the modeled system
ORGANS_INDEXES = cnwheat_simulation.Simulation.ORGANS_INDEXES
#: concatenation of :attr:`T_INDEX` and :attr:`ORGANS_INDEXES`
ORGANS_T_INDEXES = cnwheat_simulation.Simulation.ORGANS_T_INDEXES
#: organs post-processing variables
ORGANS_POSTPROCESSING_VARIABLES = ['Conc_Amino_Acids', 'Conc_Nitrates', 'Conc_Sucrose', 'Conc_cytokinins', 'Dry_Mass', 'Proteins_N_Mass',  'N_tot', 'WSC_g']
ORGANS_RUN_VARIABLES_ADDITIONAL = ['sucrose_consumption_mstruct', 'AA_consumption_mstruct', 'synthetized_mstruct']
#: concatenation of :attr:`ORGANS_T_INDEXES`, :attr:`ORGANS_RUN_VARIABLES <cnwheat.simulation.Simulation.ORGANS_RUN_VARIABLES>` and :attr:`ORGANS_POSTPROCESSING_VARIABLES`
ORGANS_RUN_POSTPROCESSING_VARIABLES = set(ORGANS_T_INDEXES + cnwheat_simulation.Simulation.ORGANS_RUN_VARIABLES + ORGANS_POSTPROCESSING_VARIABLES + ORGANS_RUN_VARIABLES_ADDITIONAL)

#: the indexes to locate the hidden zones in the modeled system
HIDDENZONE_INDEXES = cnwheat_simulation.Simulation.HIDDENZONE_INDEXES
#: concatenation of :attr:`T_INDEX` and :attr:`HIDDENZONE_INDEXES`
HIDDENZONE_T_INDEXES = cnwheat_simulation.Simulation.HIDDENZONE_T_INDEXES
#: hidden zones post-processing variables
HIDDENZONE_POSTPROCESSING_VARIABLES = ['Conc_Amino_Acids', 'Conc_Fructan', 'Conc_Proteins', 'Conc_Sucrose', 'RER', 'nb_replications', 'Cont_Fructan_DM', 'Cont_Proteins_DM', 'sum_dry_mass',
                                       'N_content', 'Cont_WSC_DM']
HIDDENZONE_RUN_VARIABLES_ADDITIONAL = ['leaf_L', 'delta_leaf_L', 'internode_L', 'leaf_pseudostem_length', 'leaf_is_emerged', 'Respi_growth', 'sucrose_consumption_mstruct', 'AA_consumption_mstruct']
#: concatenation of :attr:`HIDDENZONE_T_INDEXES`, :attr:`HIDDENZONE_RUN_VARIABLES <cnwheat.simulation.Simulation.HIDDENZONE_RUN_VARIABLES>` and :attr:`HIDDENZONE_POSTPROCESSING_VARIABLES`
HIDDENZONE_RUN_POSTPROCESSING_VARIABLES = set(HIDDENZONE_T_INDEXES + cnwheat_simulation.Simulation.HIDDENZONE_RUN_VARIABLES + HIDDENZONE_RUN_VARIABLES_ADDITIONAL + HIDDENZONE_POSTPROCESSING_VARIABLES)

#: the indexes to locate the elements in the modeled system
ELEMENTS_INDEXES = cnwheat_simulation.Simulation.ELEMENTS_INDEXES
#: concatenation of :attr:`T_INDEX` and :attr:`ELEMENTS_INDEXES`
ELEMENTS_T_INDEXES = cnwheat_simulation.Simulation.ELEMENTS_T_INDEXES
#: elements post-processing variables
ELEMENTS_POSTPROCESSING_VARIABLES = ['Conc_Amino_Acids', 'Conc_Fructan', 'Conc_Nitrates', 'Conc_Proteins', 'Conc_Starch', 'Conc_Sucrose', 'Conc_TriosesP', 'Cont_Fructan_DM',
                                     'Conc_cytokinins', 'Surfacic_NS', 'NS', 'N_content', 'N_content_total_DM', 'N_tot', 'nb_replications', 'SLA', 'SLN',
                                     'SLN_nonstruct', 'sum_dry_mass', 'Photosynthetic_efficiency', 'Cont_WSC_DM']
ELEMENTS_RUN_VARIABLES_ADDITIONAL = ['length', 'PARa']
#: concatenation of :attr:`ELEMENTS_T_INDEXES`, :attr:`ELEMENTS_RUN_VARIABLES <cnwheat.simulation.Simulation.ELEMENTS_RUN_VARIABLES>` and :attr:`ELEMENTS_POSTPROCESSING_VARIABLES`
ELEMENTS_RUN_POSTPROCESSING_VARIABLES = set(ELEMENTS_T_INDEXES + cnwheat_simulation.Simulation.ELEMENTS_RUN_VARIABLES + ELEMENTS_RUN_VARIABLES_ADDITIONAL + ELEMENTS_POSTPROCESSING_VARIABLES)

#: the indexes to locate the soils in the modeled system
SOILS_INDEXES = cnwheat_simulation.Simulation.SOILS_INDEXES
#: concatenation of :attr:`T_INDEX` and :attr:`SOILS_INDEXES`
SOILS_T_INDEXES = cnwheat_simulation.Simulation.SOILS_T_INDEXES
#: soils post-processing variables
SOILS_POSTPROCESSING_VARIABLES = []
#: concatenation of :attr:`SOILS_T_INDEXES`, :attr:`SOILS_RUN_VARIABLES <cnwheat.simulation.Simulation.SOILS_RUN_VARIABLES>` and :attr:`SOILS_POSTPROCESSING_VARIABLES`
SOILS_RUN_POSTPROCESSING_VARIABLES = SOILS_T_INDEXES + cnwheat_simulation.Simulation.SOILS_RUN_VARIABLES + SOILS_POSTPROCESSING_VARIABLES


# -------------------------------------------------
# ----------- POST-PROCESSING FUNCTIONS -----------
# ----------- DO NOT USE THEM DIRECTLY ------------
# -------------------------------------------------

[docs] class Roots: """ Post-processing to apply on Roots outputs. """ def __init__(self): pass
[docs] @staticmethod def calculate_WSC_g(sucrose): """Mass of Water Soluble Carbohydrates :param float sucrose: Amount of sucrose (µmol` C) :return: Water Soluble Carbohydrates (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS WSC_g = (sucrose * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO return WSC_g
[docs] @staticmethod def calculate_Conc_Nitrates(nitrates, mstruct): """Nitrate concentration. :param float nitrates: Amount of nitrates (µmol` N) :param float mstruct: Structural mass (g) :return: Nitrate concentration (µmol` nitrates g-1 mstruct) :rtype: float """ return nitrates / mstruct
[docs] @staticmethod def calculate_Conc_Amino_Acids(amino_acids, mstruct): """Amino_acid concentration. :param float amino_acids: Amount of amino acids (µmol` N) :param float mstruct: Structural mass (g) :return: Amino_acid concentration (µmol` amino_acids g-1 mstruct) :rtype: float """ return (amino_acids / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_N_RATIO) / mstruct
[docs] @staticmethod def calculate_conc_sucrose(sucrose, mstruct): """Sucrose concentration. :param float sucrose: Amount of sucrose (µmol` C) :param float mstruct: Structural mass (g) :return: Sucrose concentration (µmol` sucrose g-1 mstruct) :rtype: float """ return (sucrose / mstruct) / cnwheat_model.EcophysiologicalConstants.NB_C_SUCROSE
[docs] @staticmethod def calculate_conc_cytokinins(cytokinins, mstruct): """Cytokinin concentration. :param float cytokinins: Amount of cytokinins (AU) :param float mstruct: Structural mass (g) :return: cytokinins concentration (AU cytokinins g-1 mstruct) :rtype: float """ return cytokinins / mstruct
[docs] class Phloem: """ Post-processing to apply on Phloem outputs. """ def __init__(self): pass
[docs] @staticmethod def calculate_WSC_g(sucrose): """Mass of Water Soluble Carbohydrates :param float sucrose: Amount of sucrose (µmol` C) :return: Water Soluble Carbohydrates (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS WSC_g = (sucrose * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO return WSC_g
[docs] @staticmethod def calculate_conc_amino_acids(amino_acids, mstruct_axis): """Amino_acids concentration. Related to the structural dry mass of the culm. :param float amino_acids: Amount of amino_acids in phloem (µmol` N) :param float mstruct_axis: The structural dry mass of the axis (g) :return: Amino_acids concentration (µmol` amino_acids g-1 mstruct) :rtype: float """ return (amino_acids / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_N_RATIO) / mstruct_axis
[docs] @staticmethod def calculate_conc_sucrose(sucrose, mstruct_axis): """Sucrose concentration. Related to the structural dry mass of the culm :param float sucrose: Amount of sucrose in phloem (µmol` C) :param float mstruct_axis: The structural dry mass of the axis (g) :return: Sucrose concentration (µmol` sucrose g-1 mstruct) :rtype: float """ return (sucrose / cnwheat_model.EcophysiologicalConstants.NB_C_SUCROSE) / mstruct_axis
[docs] class Grains: """ Post-processing to apply on Grains outputs. """ def __init__(self): pass
[docs] @staticmethod def calculate_dry_mass(structure, starch, proteins): """Grain total dry mass. :param float structure: Grain structural C mass (µmol` C) :param float starch: Grain starch content (µmol` C) :param float proteins: Grain protein content (µmol` N) :return: Grain total dry mass (g) :rtype: float """ #: Carbohydrates mass, grain carbohydrates supposed to be mainly starch i.e. glucose polymers (C6 H12 O6) C_mass = ((structure + starch) * 1E-6 * cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO #: N mass, grain proteins were supposed to be gluten mainly composed of Glu, Gln and Pro N_mass = (proteins * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) / cnwheat_model.Grains.AMINO_ACIDS_MOLAR_MASS_N_RATIO return C_mass + N_mass
[docs] @staticmethod def calculate_WSC_g(sucrose, starch): """ Mass of Water Soluble Carbohydrates :param float sucrose: Amount of sucrose (µmol` C) :param float starch: Amount of sucrose (µmol` C) :return: Water Soluble Carbohydrates (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS WSC_g = ((sucrose * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (starch * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO) return WSC_g
[docs] @staticmethod def calculate_protein_N_mass(proteins): """Grain total protein mass. :param float proteins: Grain protein content (µmol` N) :return: Grain total protein mass (g) :rtype: float """ mass_N_proteins = proteins * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS #: Mass of nitrogen in proteins (g) # masS_proteins = mass_N_proteins / EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO #: Total mass of proteins (g) return mass_N_proteins
[docs] class HiddenZone: """ Post-processing to apply on HiddenZone outputs. """ def __init__(self): pass
[docs] @staticmethod def calculate_dry_mass(sucrose, starch, fructan, amino_acids, proteins, mstruct): """Dry mass :param float sucrose: Amount of sucrose (µmol` C) :param float starch: Amount of starch (µmol` C) :param float fructan: Amount of fructan (µmol` C) :param float amino_acids: Amount of amino acids (µmol` N) :param float proteins: Amount of proteins (µmol` N) :param float mstruct: strcural mass (g) :return: Dry mass (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS N_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS dry_mass = ((sucrose * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (starch * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (fructan * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (amino_acids * 1E-6 * N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + (proteins * 1E-6 * N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + mstruct) return dry_mass
[docs] @staticmethod def calculate_WSC_g(sucrose, fructan): """Mass of Water Soluble Carbohydrates :param float sucrose: Amount of sucrose (µmol` C) :param float fructan: Amount of fructan (µmol` C) :return: Water Soluble Carbohydrates (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS WSC_g = ((sucrose * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (fructan * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO ) return WSC_g
[docs] @staticmethod def calculate_C_g(sucrose, starch, fructan, amino_acids, proteins, mstruct): """Mass of carbon metabolites :param float sucrose: Amount of sucrose (µmol` C) :param float starch: Amount of starch (µmol` C) :param float fructan: Amount of fructan (µmol` C) :param float amino_acids: Amount of amino acids (µmol` N) :param float proteins: Amount of proteins (µmol` N) :param float mstruct: strcural mass (g) :return: Dry mass (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS N_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS C_mass = ((sucrose * 1E-6 * C_MOLAR_MASS) + (starch * 1E-6 * C_MOLAR_MASS) + (fructan * 1E-6 * C_MOLAR_MASS) + ( amino_acids * 1E-6 * N_MOLAR_MASS) * cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_C_RATIO / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + (proteins * 1E-6 * N_MOLAR_MASS) * cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_C_RATIO / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + mstruct * cnwheat_model.EcophysiologicalConstants.RATIO_C_mstruct) return C_mass
[docs] @staticmethod def calculate_N_g(amino_acids, proteins, Nstruct): """Mass of N metabolites :param float amino_acids: Amount of amino acids (µmol` N) :param float proteins: Amount of proteins (µmol` N) :param float Nstruct: N structural mass(g) :return: Dry mass (g) :rtype: float """ N_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS N_mass = ((amino_acids * 1E-6 * N_MOLAR_MASS) + (proteins * 1E-6 * N_MOLAR_MASS) + Nstruct) return N_mass
[docs] @staticmethod def calculate_fructan_g(fructan): """Mass of fructans :param float fructan: Amount of fructans (µmol` C) :return: Dry mass (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS return (fructan * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO
[docs] @staticmethod def calculate_proteins_g(proteins): """Mass of proteins :param float proteins: Amount of proteins (µmol` N) :return: Dry mass (g) :rtype: float """ N_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS return (proteins * 1E-6 * N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.PROTEINS_MOLAR_MASS_N_RATIO
[docs] @staticmethod def calculate_Conc_Amino_Acids(amino_acids, mstruct): """Amino acid concentration. :param float amino_acids: N amino acids (µmol` N) :param float mstruct: Structural mass :return: Amino_acid concentration (µmol` amino acids g-1 mstruct) :rtype: float """ return (amino_acids / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_N_RATIO) / mstruct
[docs] @staticmethod def calculate_conc_sucrose(sucrose, mstruct): """Sucrose concentration. :param float sucrose: C sucrose (µmol` C) :param float mstruct: Structural mass :return: Sucrose concentration (µmol` sucrose g-1 mstruct) :rtype: float """ return (sucrose / mstruct) / cnwheat_model.EcophysiologicalConstants.NB_C_SUCROSE
[docs] @staticmethod def calculate_conc_fructan(fructan, mstruct): """Fructan concentration. :param float fructan: C fructan (µmol` C) :param float mstruct: Structural mass :return: Fructan concentration (µmol` fructan g-1 mstruct, eq. glucose). :rtype: float """ return (fructan / mstruct) / cnwheat_model.EcophysiologicalConstants.NB_C_HEXOSES
[docs] @staticmethod def calculate_conc_protein(proteins, mstruct): """Proteins concentration. :param float proteins: N proteins (µmol` N) :param float mstruct: Structural mass :return: Protein concentration (g proteins g-1 mstruct) :rtype: float """ mass_N_proteins = proteins * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS #: Mass of N in proteins (g) masS_proteins = mass_N_proteins / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO #: Total mass of proteins (g) return masS_proteins / mstruct
[docs] @staticmethod def calculate_RER(delta_leaf_L, leaf_L, delta_t): """Relative Extension Rate. :param float delta_leaf_L: delta of leaf length between t and t-1 (m) :param float leaf_L: leaf length (m) :param float delta_t: delta_t (s) :return: Relative Extension Rate (s-1) :rtype: float """ return (delta_leaf_L / delta_t) / leaf_L
[docs] class Element: """ Post-processing to apply on Element outputs. """ def __init__(self): pass
[docs] @staticmethod def calculate_dry_mass(triosesP, sucrose, starch, fructan, nitrates, amino_acids, proteins, mstruct): """Dry mass :param triosesP: Amount of triose phosphates (µmol` C) :param float sucrose: Amount of sucrose (µmol` C) :param float starch: Amount of sucrose (µmol` C) :param float fructan: Amount of sucrose (µmol` C) :param float nitrates: Amount of nitrates (µmol` N) :param float amino_acids: Amount of sucrose (µmol` N) :param float proteins: Amount of sucrose (µmol` N) :param float mstruct: strcural mass (g) :return: Dry mass (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS N_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS dry_mass = ((triosesP * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.TRIOSESP_MOLAR_MASS_C_RATIO + (sucrose * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (starch * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (fructan * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (nitrates * 1E-6 * N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.NITRATES_MOLAR_MASS_N_RATIO + (amino_acids * 1E-6 * N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + (proteins * 1E-6 * N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + mstruct) return dry_mass
[docs] @staticmethod def calculate_WSC_g(triosesP, sucrose, starch, fructan): """ Mass of Water Soluble Carbohydrates :param triosesP: Amount of triose phosphates (µmol` C) :param float sucrose: Amount of sucrose (µmol` C) :param float starch: Amount of sucrose (µmol` C) :param float fructan: Amount of sucrose (µmol` C) :return: Water Soluble Carbohydrates (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS WSC_g = ((triosesP * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.TRIOSESP_MOLAR_MASS_C_RATIO + (sucrose * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (starch * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (fructan * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO ) return WSC_g
[docs] @staticmethod def calculate_fructan_g(fructan): """Mass of fructans :param float fructan: Amount of fructans (µmol` C) :return: Dry mass (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS return (fructan * 1E-6 * C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO
[docs] @staticmethod def calculate_C_g(triosesP, sucrose, starch, fructan, amino_acids, proteins, mstruct): """Mass of carbon metabolites :param float triosesP: Amount of triose phosphates (µmol` C) :param float sucrose: Amount of sucrose (µmol` C) :param float starch: Amount of starch (µmol` C) :param float fructan: Amount of fructan (µmol` C) :param float amino_acids: Amount of amino acids (µmol` N) :param float proteins: Amount of proteins (µmol` N) :param float mstruct: strcural mass (g) :return: Dry mass (g) :rtype: float """ C_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS N_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS C_mass = ((triosesP * 1E-6 * C_MOLAR_MASS) + (sucrose * 1E-6 * C_MOLAR_MASS) + (starch * 1E-6 * C_MOLAR_MASS) + (fructan * 1E-6 * C_MOLAR_MASS) + ( amino_acids * 1E-6 * N_MOLAR_MASS) * cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_C_RATIO / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + (proteins * 1E-6 * N_MOLAR_MASS) * cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_C_RATIO / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + mstruct * cnwheat_model.EcophysiologicalConstants.RATIO_C_mstruct) return C_mass
[docs] @staticmethod def calculate_N_g(nitrates, amino_acids, proteins, Nstruct): """Mass of N metabolites :param float nitrates: Amount of nitrates (µmol` N) :param float amino_acids: Amount of amino acids (µmol` N) :param float proteins: Amount of proteins (µmol` N) :param float Nstruct: N structural mass(g) :return: Dry mass (g) :rtype: float """ N_MOLAR_MASS = cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS N_mass = ((nitrates * 1E-6 * N_MOLAR_MASS) + (amino_acids * 1E-6 * N_MOLAR_MASS) + (proteins * 1E-6 * N_MOLAR_MASS) + Nstruct) return N_mass
[docs] @staticmethod def calculate_conc_triosesP(triosesP, mstruct): """Triose Phosphates concentration. :param float triosesP: Amount of triose phosphates (µmol` C) :param float mstruct: Structural mass :return: Triose phosphates concentration (µmol` triosesP g-1 mstruct) :rtype: float """ return (triosesP / mstruct) / cnwheat_model.EcophysiologicalConstants.NB_C_TRIOSEP
[docs] @staticmethod def calculate_conc_sucrose(sucrose, mstruct): """Sucrose concentration. :param float sucrose: Amount of sucrose (µmol` C) :param float mstruct: Structural mass :return: Sucrose concentration (µmol` sucrose g-1 mstruct) :rtype: float """ return (sucrose / mstruct) / cnwheat_model.EcophysiologicalConstants.NB_C_SUCROSE
[docs] @staticmethod def calculate_conc_starch(starch, mstruct): """Starch concentration. :param float starch: Amount of sucrose (µmol` C) :param float mstruct: Structural mass :return: Starch concentration (µmol` starch g-1 mstruct) :rtype: float """ return (starch / mstruct) / cnwheat_model.EcophysiologicalConstants.NB_C_HEXOSES
[docs] @staticmethod def calculate_conc_fructan(fructan, mstruct): """Fructan concentration. :param float fructan: Amount of fructan (µmol` C) :param float mstruct: Structural mass :return: Fructan concentration (µmol` fructan g-1 mstruct, eq. glucose). :rtype: float """ return (fructan / mstruct) / cnwheat_model.EcophysiologicalConstants.NB_C_HEXOSES
[docs] @staticmethod def calculate_Conc_Nitrates(nitrates, mstruct): """Nitrate concentration. :param float nitrates: Amount of nitrates (µmol` N) :param float mstruct: Structural mass :return: Nitrate concentration (µmol` nitrates g-1 mstruct) :rtype: float """ return nitrates / mstruct
[docs] @staticmethod def calculate_Conc_Amino_Acids(amino_acids, mstruct): """Amino_acid concentration. :param float amino_acids: Amount of amino acids (µmol` N) :param float mstruct: Structural mass :return: Amino_acid concentration (µmol` amino acids g-1 mstruct) :rtype: float """ return (amino_acids / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_N_RATIO) / mstruct
[docs] @staticmethod def calculate_conc_proteins(proteins, mstruct): """Protein concentration. :param float proteins: Amount of proteins (µmol` N) :param float mstruct: Structural mass :return: Protein concentration (g proteins g-1 mstruct) :rtype: float """ mass_N_proteins = proteins * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS #: Mass of N in proteins (g) mass_proteins = mass_N_proteins / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO #: Total mass of proteins (g) return mass_proteins / mstruct
[docs] @staticmethod def calculate_conc_cytokinins(cytokinins, mstruct): """Cytokinin concentration. :param float cytokinins: Amount of cytokinins (AU) :param float mstruct: Structural mass :return: Cytokinin concentration (AU g-1 mstruct) :rtype: float """ return cytokinins / mstruct
[docs] @staticmethod def calculate_SLN(nitrates, amino_acids, proteins, Nstruct, green_area): """ Surfacic Leaf Nitrogen (SLN, g.m-2) :param float nitrates: Amount of nitrates (µmol` N) :param float amino_acids: Amount of amino_acids (µmol` N) :param float proteins: Amount of proteins (µmol` N) :param float Nstruct: Structural N (g) :param float green_area: Green area (m-2) :return: Surfacic Leaf Nitrogen (SLN, g.m-2) :rtype: float """ mass_N_tot = (nitrates + amino_acids + proteins) * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS + Nstruct return mass_N_tot / green_area
[docs] @staticmethod def calculate_SLN_nonstruct(nitrates, amino_acids, proteins, green_area): """ Surfacic Leaf Nitrogen (SLN, g.m-2) :param float nitrates: Amount of nitrates (µmol` N) :param float amino_acids: Amount of amino_acids (µmol` N) :param float proteins: Amount of proteins (µmol` N) :param float green_area: Green area (m-2) :return: Surfacic Leaf Nitrogen (SLN, g.m-2) :rtype: float """ mass_N_tot = (nitrates + amino_acids + proteins) * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS return mass_N_tot / green_area
[docs] @staticmethod def calculate_SLA(dry_mass, green_area): """Specific Leaf Area (SLA, m2.kg-1) :param float dry_mass: Dry mass (g) :param float green_area: Green area (m-2) :return: Specific Leaf Area (SLA, m2 kg-1) :rtype: float """ return green_area / (dry_mass * 10 ** -3)
[docs] @staticmethod def calculate_surfacic_non_structural(dry_mass, mstruct, green_area): """Surfacic content of non structural mass :param float dry_mass: Dry mass (g) :param float mstruct: Structural mass (g) :param float green_area: Green area (m-2) :return: Surfacic non structural mass (g m-2) :rtype: float """ return (dry_mass - mstruct) / green_area
[docs] @staticmethod def calculate_ratio_non_structural(dry_mass, mstruct): """Surfacic content of nitrogen :param float dry_mass: Dry mass (g) :param float mstruct: Structural mass (g) :return: Surfacic non structural mass (g m-2) :rtype: float """ return (1 - mstruct / dry_mass) * 100
# ----------------------------------------------------------------------------- # --------------------- POST-PROCESSING FRONT-END ----------------------------- # PLEASE USE THIS FUNCTION TO APPLY POST-PROCESSING ON THE OUTPUT OF CN-WHEAT - # -----------------------------------------------------------------------------
[docs] def postprocessing(plants_df=None, axes_df=None, metamers_df=None, hiddenzones_df=None, organs_df=None, elements_df=None, soils_df=None, delta_t=1): """ Compute post-processing from CN-Wheat outputs, and format the post-processing to :class:`dataframes <pandas.DataFrame>`. For each post-processing output dataframe: * compute post-processing from CN-Wheat outputs, * concatenate CN-Wheat outputs and post-processing and place the results in a jointed dataframe, * reorder the columns of the dataframes according to :attr:`PLANTS_RUN_POSTPROCESSING_VARIABLES`, :attr:`AXES_RUN_POSTPROCESSING_VARIABLES`, :attr:`PHYTOMERS_RUN_POSTPROCESSING_VARIABLES`, :attr:`ORGANS_RUN_POSTPROCESSING_VARIABLES`, :attr:`HIDDENZONE_RUN_POSTPROCESSING_VARIABLES`, :attr:`ELEMENTS_RUN_POSTPROCESSING_VARIABLES` and :attr:`SOILS_RUN_POSTPROCESSING_VARIABLES`, * and convert the indexes of plants and metamers to integers (if relevant). :param pandas.DataFrame plants_df: CN-Wheat outputs at plant scale (see :attr:`simulation.Simulation.PLANTS_RUN_VARIABLES`) :param pandas.DataFrame axes_df: CN-Wheat outputs at axis scale (see :attr:`simulation.Simulation.AXES_RUN_VARIABLES`) :param pandas.DataFrame metamers_df: CN-Wheat outputs at phytomer scale (see :attr:`simulation.Simulation.PHYTOMERS_RUN_VARIABLES`) :param pandas.DataFrame hiddenzones_df: CN-Wheat outputs at hidden zone scale (see :attr:`simulation.Simulation.HIDDENZONE_RUN_VARIABLES`) :param pandas.DataFrame organs_df: CN-Wheat outputs at organ scale (see :attr:`simulation.Simulation.ORGANS_RUN_VARIABLES`) :param pandas.DataFrame elements_df: CN-Wheat outputs at element scale (see :attr:`simulation.Simulation.ELEMENTS_RUN_VARIABLES`) :param pandas.DataFrame soils_df: CN-Wheat outputs at soil scale (see :attr:`simulation.Simulation.SOILS_RUN_VARIABLES`) :param float delta_t: Delta t between 2 outputs (in seconds). :return: post-processing for each scale: * plant (see :attr:`PLANTS_RUN_POSTPROCESSING_VARIABLES`) * axis (see :attr:`AXES_RUN_POSTPROCESSING_VARIABLES`) * metamer (see :attr:`PHYTOMERS_RUN_POSTPROCESSING_VARIABLES`) * organ (see :attr:`ORGANS_RUN_POSTPROCESSING_VARIABLES`) * hidden zone (see :attr:`HIDDENZONE_RUN_POSTPROCESSING_VARIABLES`) * element (see :attr:`ELEMENTS_RUN_POSTPROCESSING_VARIABLES`) * and soil (see :attr:`SOILS_RUN_POSTPROCESSING_VARIABLES`) depending of the dataframes given as argument. For example, if user passes only dataframes `plants_df`, `axes_df` and `metamers_df`, then only post-processing dataframes of plants, axes and metamers are returned. :rtype: tuple [pandas.DataFrame] """ returned_dataframes = [] # plants if plants_df is not None: pp_plants_df = pd.concat([plants_df, pd.DataFrame(columns=PLANTS_POSTPROCESSING_VARIABLES)], sort=False) pp_plants_df = pp_plants_df.reindex(PLANTS_RUN_POSTPROCESSING_VARIABLES, axis=1, copy=False) pp_plants_df['plant'] = pp_plants_df['plant'].astype(int) returned_dataframes.append(pp_plants_df) else: returned_dataframes.append(pd.DataFrame({'A': []})) # metamers if metamers_df is not None: pp_metamers_df = pd.concat([metamers_df, pd.DataFrame(columns=PHYTOMERS_POSTPROCESSING_VARIABLES)], sort=False) pp_metamers_df = pp_metamers_df.reindex(PHYTOMERS_RUN_POSTPROCESSING_VARIABLES, axis=1, copy=False) pp_metamers_df[['plant', 'metamer']] = pp_metamers_df[['plant', 'metamer']].astype(int) returned_dataframes.append(pp_metamers_df) else: returned_dataframes.append(pd.DataFrame({'A': []})) # organs if organs_df is not None and axes_df is not None: axes_df = axes_df[axes_df['axis'] == 'MS'].copy() # TODO : Temporary ! pp_organs_df = pd.concat([organs_df, pd.DataFrame(columns=ORGANS_POSTPROCESSING_VARIABLES)], sort=False) organs_df['sum_dry_mass'] = (((organs_df.fillna(0)['structure'] + organs_df.fillna(0)[ 'starch']) * 1E-6 * cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO) + (organs_df.fillna(0)[ 'sucrose'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (organs_df.fillna(0)['starch'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.HEXOSE_MOLAR_MASS_C_RATIO + (organs_df.fillna(0)[ 'nitrates'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.NITRATES_MOLAR_MASS_N_RATIO + (organs_df.fillna(0)[ 'amino_acids'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + (organs_df.fillna(0)[ 'proteins'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + organs_df.fillna(0)['mstruct']) organs_df['C_g'] = ((organs_df.fillna(0)['sucrose'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS) + (organs_df.fillna(0)['starch'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.C_MOLAR_MASS) + (organs_df.fillna(0)[ 'amino_acids'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) * cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_C_RATIO / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + (organs_df.fillna(0)['proteins'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) * cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_C_RATIO / cnwheat_model.EcophysiologicalConstants.AMINO_ACIDS_MOLAR_MASS_N_RATIO + organs_df.fillna(0)['mstruct'] * cnwheat_model.EcophysiologicalConstants.RATIO_C_mstruct) organs_df['N_g'] = ((organs_df.fillna(0)['nitrates'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) + (organs_df.fillna(0)['amino_acids'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) + (organs_df.fillna(0)['proteins'] * 1E-6 * cnwheat_model.EcophysiologicalConstants.N_MOLAR_MASS) + organs_df.fillna(0)['Nstruct']) pp_organs_df['N_tot'] = organs_df['N_g'] # roots roots_df = organs_df.loc[organs_df.organ == 'roots'] pp_organs_df.loc[pp_organs_df.organ == 'roots', 'WSC_g'] = Roots.calculate_WSC_g(roots_df['sucrose']) pp_organs_df.loc[pp_organs_df.organ == 'roots', 'Conc_Nitrates'] = Roots.calculate_Conc_Nitrates(roots_df['nitrates'], roots_df['mstruct']) pp_organs_df.loc[pp_organs_df.organ == 'roots', 'Conc_Amino_Acids'] = Roots.calculate_Conc_Amino_Acids(roots_df['amino_acids'], roots_df['mstruct']) pp_organs_df.loc[pp_organs_df.organ == 'roots', 'Conc_Sucrose'] = Roots.calculate_conc_sucrose(roots_df['sucrose'], roots_df['mstruct']) pp_organs_df.loc[pp_organs_df.organ == 'roots', 'Conc_cytokinins'] = Roots.calculate_conc_cytokinins(roots_df['cytokinins'], roots_df['mstruct']) pp_organs_df.loc[pp_organs_df.organ == 'roots', 'Conc_cytokinins'] = Roots.calculate_conc_cytokinins(roots_df['cytokinins'], roots_df['mstruct']) R_residual = np.array( list(map(respiwheat_model.RespirationModel.R_residual, roots_df['sucrose'], roots_df['mstruct'] * cnwheat_model.Roots.PARAMETERS.ALPHA, roots_df['Total_Organic_Nitrogen'], soils_df['Tsoil']))) pp_organs_df.loc[pp_organs_df.organ == 'roots', 'R_residual'] = R_residual # phloem phloems_df = organs_df.loc[organs_df.organ == 'phloem'] pp_organs_df.loc[pp_organs_df.organ == 'phloem', 'WSC_g'] = Phloem.calculate_WSC_g(phloems_df['sucrose']) pp_organs_df.loc[pp_organs_df.organ == 'phloem', 'Conc_Amino_Acids'] = Phloem.calculate_conc_amino_acids(phloems_df['amino_acids'], axes_df.set_index(phloems_df.index)['mstruct']) pp_organs_df.loc[pp_organs_df.organ == 'phloem', 'Conc_Sucrose'] = Phloem.calculate_conc_sucrose(phloems_df['sucrose'], axes_df.set_index(phloems_df.index)['mstruct']) # grains grains_df = organs_df.loc[organs_df.organ == 'grains'] pp_organs_df.loc[pp_organs_df.organ == 'grains', 'Dry_Mass'] = Grains.calculate_dry_mass(grains_df['structure'], grains_df['starch'], grains_df['proteins']) pp_organs_df.loc[pp_organs_df.organ == 'grains', 'WSC_g'] = Grains.calculate_WSC_g(grains_df['sucrose'], grains_df['starch']) pp_organs_df.loc[pp_organs_df.organ == 'grains', 'Proteins_N_Mass'] = Grains.calculate_protein_N_mass(grains_df['proteins']) pp_organs_df = pp_organs_df.reindex(columns=ORGANS_RUN_POSTPROCESSING_VARIABLES, copy=False) pp_organs_df['plant'] = pp_organs_df['plant'].astype(int) returned_dataframes.append(pp_organs_df) else: returned_dataframes.append(pd.DataFrame({'A': []})) # elements if elements_df is not None: elements_df['sum_dry_mass'] = Element.calculate_dry_mass(elements_df.fillna(0)['triosesP'], elements_df.fillna(0)['sucrose'], elements_df.fillna(0)['starch'], elements_df.fillna(0)['fructan'], elements_df.fillna(0)['nitrates'], elements_df.fillna(0)['amino_acids'], elements_df.fillna(0)['proteins'], elements_df['mstruct']) elements_df['sum_dry_mass_total'] = Element.calculate_dry_mass(elements_df.fillna(0)['triosesP'], elements_df.fillna(0)['sucrose'], elements_df.fillna(0)['starch'], elements_df.fillna(0)['fructan'], elements_df.fillna(0)['nitrates'], elements_df.fillna(0)['amino_acids'], elements_df.fillna(0)['proteins'], elements_df['max_mstruct'] + elements_df['Nresidual']) elements_df['C_g'] = Element.calculate_C_g(elements_df.fillna(0)['triosesP'], elements_df.fillna(0)['sucrose'], elements_df.fillna(0)['starch'], elements_df.fillna(0)['fructan'], elements_df.fillna(0)['amino_acids'], elements_df.fillna(0)['proteins'], elements_df['mstruct']) elements_df['N_g'] = Element.calculate_N_g(elements_df.fillna(0)['nitrates'], elements_df.fillna(0)['amino_acids'], elements_df.fillna(0)['proteins'], elements_df['Nstruct']) elements_df['N_g_total'] = Element.calculate_N_g(elements_df.fillna(0)['nitrates'], elements_df.fillna(0)['amino_acids'], elements_df.fillna(0)['proteins'], elements_df['Nstruct'] + elements_df['Nresidual']) elements_df['WSC_g'] = Element.calculate_WSC_g(elements_df.fillna(0)['triosesP'], elements_df.fillna(0)['sucrose'], elements_df.fillna(0)['starch'], elements_df.fillna(0)['fructan'], ) pp_elements_df = pd.concat([elements_df, pd.DataFrame(columns=ELEMENTS_POSTPROCESSING_VARIABLES, dtype='float64')], sort=False) pp_elements_df.loc[:, 'Conc_TriosesP'] = Element.calculate_conc_triosesP(elements_df['triosesP'], elements_df['mstruct']) pp_elements_df.loc[:, 'Conc_Starch'] = Element.calculate_conc_starch(elements_df['starch'], elements_df['mstruct']) pp_elements_df.loc[:, 'Conc_Sucrose'] = Element.calculate_conc_sucrose(elements_df['sucrose'], elements_df['mstruct']) pp_elements_df.loc[:, 'Conc_Fructan'] = Element.calculate_conc_fructan(elements_df['fructan'], elements_df['mstruct']) pp_elements_df.loc[:, 'Conc_Nitrates'] = Element.calculate_Conc_Nitrates(elements_df['nitrates'], elements_df['mstruct']) pp_elements_df.loc[:, 'Conc_Amino_Acids'] = Element.calculate_Conc_Amino_Acids(elements_df['amino_acids'], elements_df['mstruct']) pp_elements_df.loc[:, 'Conc_Proteins'] = Element.calculate_conc_proteins(elements_df['proteins'], elements_df['mstruct']) pp_elements_df.loc[:, 'Conc_cytokinins'] = Element.calculate_conc_cytokinins(elements_df['cytokinins'], elements_df['mstruct']) pp_elements_df.loc[:, 'Cont_Fructan_DM'] = Element.calculate_fructan_g(elements_df['fructan']) / elements_df['sum_dry_mass'] * 100 pp_elements_df.loc[:, 'Cont_WSC_DM'] = elements_df['WSC_g'] / elements_df['sum_dry_mass'] * 100 pp_elements_df.loc[:, 'Surfacic_NS'] = Element.calculate_surfacic_non_structural(elements_df['sum_dry_mass'], elements_df['mstruct'], elements_df['green_area']) pp_elements_df.loc[:, 'NS'] = Element.calculate_ratio_non_structural(elements_df['sum_dry_mass'], elements_df['mstruct']) pp_elements_df.loc[:, 'N_content'] = elements_df['N_g'] / elements_df['sum_dry_mass'] * 100 pp_elements_df.loc[:, 'N_content_total_DM'] = elements_df['N_g_total'] / elements_df['sum_dry_mass_total'] * 100 pp_elements_df.loc[:, 'N_tot'] = elements_df['N_g_total'] pp_elements_df.loc[:, 'SLN'] = Element.calculate_SLN(elements_df['nitrates'], elements_df['amino_acids'], elements_df['proteins'], elements_df['Nstruct'], elements_df['green_area']) pp_elements_df.loc[pp_elements_df['is_growing'] == 1., 'SLN'] = np.nan pp_elements_df.loc[:, 'SLN_nonstruct'] = Element.calculate_SLN_nonstruct(elements_df['nitrates'], elements_df['amino_acids'], elements_df['proteins'], elements_df['green_area']) pp_elements_df.loc[pp_elements_df['is_growing'] == 1., 'SLN_nonstruct'] = np.nan pp_elements_df.loc[:, 'SLA'] = Element.calculate_SLA(elements_df['sum_dry_mass'], elements_df['green_area']) pp_elements_df.loc[pp_elements_df['is_growing'] == 1., 'SLA'] = np.nan pp_elements_df.loc[:, 'Photosynthetic_efficiency'] = elements_df['Ag'] / elements_df['PARa'] grouped = elements_df.groupby('organ') for organ_type, parameters_class in \ (('ear', cnwheat_parameters.CHAFF_ELEMENT_PARAMETERS), ('blade', cnwheat_parameters.LAMINA_ELEMENT_PARAMETERS), ('internode', cnwheat_parameters.INTERNODE_ELEMENT_PARAMETERS), ('peduncle', cnwheat_parameters.PEDUNCLE_ELEMENT_PARAMETERS), ('sheath', cnwheat_parameters.SHEATH_ELEMENT_PARAMETERS)): if organ_type not in grouped.groups: continue group = grouped.get_group(organ_type) if len(group) == 0: # TODO: faire mm tri que dans simulation de cnwheat (surface nulle) continue curr_organ_elements_df = elements_df.loc[group.index] pp_curr_organ_elements_df = pp_elements_df.loc[group.index] R_residual = np.vectorize(respiwheat_model.RespirationModel.R_residual)(curr_organ_elements_df['sucrose'], curr_organ_elements_df['mstruct'] * parameters_class.ALPHA, curr_organ_elements_df['Total_Organic_Nitrogen'], curr_organ_elements_df['Ts']) pp_curr_organ_elements_df.loc[:, 'R_residual'] = R_residual pp_elements_df = pp_elements_df.reindex(columns=ELEMENTS_RUN_POSTPROCESSING_VARIABLES, copy=False) pp_elements_df[['plant', 'metamer']] = pp_elements_df[['plant', 'metamer']].astype(int) returned_dataframes.append(pp_elements_df) else: returned_dataframes.append(pd.DataFrame({'A': []})) # hidden zones if hiddenzones_df is not None: # hiddenzones_df = hiddenzones_df.merge(nb_replications_df, on='metamer') hiddenzones_df['sum_dry_mass'] = HiddenZone.calculate_dry_mass(hiddenzones_df.fillna(0)['sucrose'], 0, # hiddenzones_df.fillna(0)['starch'], hiddenzones_df.fillna(0)['fructan'], hiddenzones_df.fillna(0)['amino_acids'], hiddenzones_df.fillna(0)['proteins'], hiddenzones_df['mstruct']) hiddenzones_df['C_g'] = HiddenZone.calculate_C_g(hiddenzones_df.fillna(0)['sucrose'], 0, # hiddenzones_df.fillna(0)['starch'], hiddenzones_df.fillna(0)['fructan'], hiddenzones_df.fillna(0)['amino_acids'], hiddenzones_df.fillna(0)['proteins'], hiddenzones_df['mstruct']) hiddenzones_df['N_g'] = HiddenZone.calculate_N_g(hiddenzones_df.fillna(0)['amino_acids'], hiddenzones_df.fillna(0)['proteins'], hiddenzones_df['leaf_enclosed_Nstruct'] + hiddenzones_df['internode_enclosed_Nstruct']) hiddenzones_df['WSC_g'] = HiddenZone.calculate_WSC_g(hiddenzones_df.fillna(0)['sucrose'], hiddenzones_df.fillna(0)['fructan']) pp_hiddenzones_df = pd.concat([hiddenzones_df, pd.DataFrame(columns=HIDDENZONE_POSTPROCESSING_VARIABLES, dtype='float64')], sort=False) pp_hiddenzones_df.loc[:, 'Conc_Amino_Acids'] = HiddenZone.calculate_Conc_Amino_Acids(hiddenzones_df['amino_acids'], hiddenzones_df['mstruct']) pp_hiddenzones_df.loc[:, 'Conc_Fructan'] = HiddenZone.calculate_conc_fructan(hiddenzones_df['fructan'], hiddenzones_df['mstruct']) pp_hiddenzones_df.loc[:, 'Conc_Proteins'] = HiddenZone.calculate_conc_protein(hiddenzones_df['proteins'], hiddenzones_df['mstruct']) pp_hiddenzones_df.loc[:, 'Conc_Sucrose'] = HiddenZone.calculate_conc_sucrose(hiddenzones_df['sucrose'], hiddenzones_df['mstruct']) pp_hiddenzones_df.loc[:, 'Cont_Fructan_DM'] = HiddenZone.calculate_fructan_g(hiddenzones_df['fructan']) / hiddenzones_df['sum_dry_mass'] * 100 pp_hiddenzones_df.loc[:, 'Cont_Proteins_DM'] = HiddenZone.calculate_proteins_g(hiddenzones_df['proteins']) / hiddenzones_df['sum_dry_mass'] * 100 pp_hiddenzones_df.loc[:, 'Cont_WSC_DM'] = hiddenzones_df['WSC_g'] / hiddenzones_df['sum_dry_mass'] * 100 pp_hiddenzones_df.loc[:, 'N_content'] = pp_hiddenzones_df['N_g'] / pp_hiddenzones_df['sum_dry_mass'] * 100 if set(hiddenzones_df.columns).issuperset(['delta_leaf_L', 'leaf_L']): # this is temporary: those post-processing should be done in model "elong-wheat" pp_hiddenzones_df.loc[:, 'RER'] = HiddenZone.calculate_RER(hiddenzones_df['delta_leaf_L'], hiddenzones_df['leaf_L'], delta_t) pp_hiddenzones_df = pp_hiddenzones_df.reindex(columns=HIDDENZONE_RUN_POSTPROCESSING_VARIABLES, copy=False) pp_hiddenzones_df[['plant', 'metamer']] = pp_hiddenzones_df[['plant', 'metamer']].astype(int) returned_dataframes.append(pp_hiddenzones_df) else: returned_dataframes.append(pd.DataFrame({'A': []})) # axes if axes_df is not None: axes_df = axes_df[axes_df['axis'] == 'MS'].copy() # TODO : Temporary ! pp_axes_df = pd.concat([axes_df, pd.DataFrame(columns=AXES_POSTPROCESSING_VARIABLES)], sort=False) # Integrated variables TODO : Homogeneiser la structure de ce bout de code if (hiddenzones_df is not None) and (organs_df is not None) and (elements_df is not None): # Add missing row if any axes_row_keys = organs_df[AXES_T_INDEXES].drop_duplicates() pp_axes_df = pp_axes_df.merge(axes_row_keys, how='outer', on=AXES_T_INDEXES) pp_axes_df.sort_values(AXES_T_INDEXES, inplace=True) # Make sure axes_df is sorted pp_axes_df.reset_index(drop=True, inplace=True) # Roots dry_mass_roots = organs_df[(organs_df['organ'] == 'roots')].groupby(['t', 'plant', 'axis'])['sum_dry_mass'].agg('sum') # Total mstruct shoot and root hz_df_MS = hiddenzones_df[hiddenzones_df['axis'] == 'MS'].copy() elt_df_MS = elements_df[elements_df['axis'] == 'MS'].copy() hz_df_MS['mstruct_tillers'] = hz_df_MS['mstruct'] * hz_df_MS['nb_replications'] elt_df_MS['mstruct_tillers'] = elt_df_MS['mstruct'] * elt_df_MS['nb_replications'] sum_mstruct_shoot = hz_df_MS.groupby(['t', 'plant', 'axis'])['mstruct_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['mstruct_tillers'].agg('sum') sum_mstruct_laminae = elt_df_MS[elt_df_MS.element == 'LeafElement1'].groupby(['t', 'plant', 'axis'])['mstruct_tillers'].agg('sum') sum_mstruct_stem = sum_mstruct_shoot - sum_mstruct_laminae sum_mstruct_roots = organs_df[(organs_df['organ'] == 'roots')].groupby(['t', 'plant', 'axis'])['mstruct'].agg('sum') shoot_roots_mstruct_ratio = sum_mstruct_shoot / sum_mstruct_roots # Phloem phloem_shoot_root = 1 / (1 + 1 / shoot_roots_mstruct_ratio) phloem_laminae = sum_mstruct_laminae / (sum_mstruct_shoot + sum_mstruct_roots) phloem_stem = sum_mstruct_stem / (sum_mstruct_shoot + sum_mstruct_roots) sum_dry_mass_phloem = organs_df[(organs_df['organ'] == 'phloem')].groupby(['t', 'plant', 'axis'])['sum_dry_mass'].agg('sum') sum_dry_mass_phloem_shoot = sum_dry_mass_phloem * phloem_shoot_root sum_dry_mass_phloem_laminae = sum_dry_mass_phloem * phloem_laminae sum_dry_mass_phloem_roots = sum_dry_mass_phloem * (1 - phloem_shoot_root) sum_N_g_phloem_shoot = organs_df[(organs_df['organ'] == 'phloem')].groupby(['t', 'plant', 'axis'])['N_g'].agg('sum') * phloem_shoot_root sum_C_g_phloem_shoot = organs_df[(organs_df['organ'] == 'phloem')].groupby(['t', 'plant', 'axis'])['C_g'].agg('sum') * phloem_shoot_root sum_WSC_g_phloem_shoot = pp_organs_df[(organs_df['organ'] == 'phloem')].groupby(['t', 'plant', 'axis'])['WSC_g'].agg('sum') * phloem_shoot_root sum_WSC_g_phloem_laminae = pp_organs_df[(organs_df['organ'] == 'phloem')].groupby(['t', 'plant', 'axis'])['WSC_g'].agg('sum') * phloem_laminae sum_WSC_g_phloem_stem = pp_organs_df[(organs_df['organ'] == 'phloem')].groupby(['t', 'plant', 'axis'])['WSC_g'].agg('sum') * phloem_stem sum_WSC_g_phloem_roots = pp_organs_df[(organs_df['organ'] == 'phloem')].groupby(['t', 'plant', 'axis'])['WSC_g'].agg('sum') * (1 - phloem_shoot_root) # Total shoot hz_df_MS['sum_dry_mass_tillers'] = hz_df_MS['sum_dry_mass'] * hz_df_MS['nb_replications'] elt_df_MS['sum_dry_mass_tillers'] = elt_df_MS['sum_dry_mass'] * elt_df_MS['nb_replications'] elt_df_MS['sum_dry_mass_total_tillers'] = elt_df_MS['sum_dry_mass_total'] * elt_df_MS['nb_replications'] sum_dry_mass_shoot = sum_dry_mass_phloem_shoot + \ hz_df_MS.groupby(['t', 'plant', 'axis'])['sum_dry_mass_tillers'].agg('sum') + \ elt_df_MS.groupby(['t', 'plant', 'axis'])['sum_dry_mass_tillers'].agg('sum') sum_dry_mass_laminae = sum_dry_mass_phloem_laminae + \ elt_df_MS[elt_df_MS.element == 'LeafElement1'].groupby(['t', 'plant', 'axis'])['sum_dry_mass_tillers'].agg('sum') sum_dry_mass_stem = sum_dry_mass_shoot - sum_dry_mass_laminae sum_dry_mass_total_shoot = sum_dry_mass_phloem_shoot + \ hz_df_MS.groupby(['t', 'plant', 'axis'])['sum_dry_mass_tillers'].agg('sum') + \ elt_df_MS.groupby(['t', 'plant', 'axis'])['sum_dry_mass_total_tillers'].agg('sum') # Total root sum_dry_mass_roots = sum_dry_mass_phloem_roots + dry_mass_roots # Total shoot + roots sum_dry_mass = sum_dry_mass_shoot + sum_dry_mass_roots sum_mstruct = sum_mstruct_roots + sum_mstruct_shoot # N content hz_df_MS['N_g_tillers'] = hz_df_MS['N_g'] * hz_df_MS['nb_replications'] elt_df_MS['N_g_tillers'] = elt_df_MS['N_g'] * elt_df_MS['nb_replications'] elt_df_MS['N_g_total_tillers'] = elt_df_MS['N_g_total'] * elt_df_MS['nb_replications'] sum_N_g = (organs_df[organs_df['axis'] == 'MS'].groupby(['t', 'plant', 'axis'])['N_g'].agg('sum') + hz_df_MS.groupby(['t', 'plant', 'axis'])['N_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['N_g_tillers'].agg('sum')) sum_N_g_total = (organs_df[organs_df['axis'] == 'MS'].groupby(['t', 'plant', 'axis'])['N_g'].agg('sum') + hz_df_MS.groupby(['t', 'plant', 'axis'])['N_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['N_g_total_tillers'].agg('sum')) N_content = sum_N_g / sum_dry_mass * 100 N_content_mstruct = sum_N_g / sum_mstruct * 100 sum_N_g_shoot = (sum_N_g_phloem_shoot + hz_df_MS.groupby(['t', 'plant', 'axis'])['N_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['N_g_tillers'].agg('sum')) sum_N_g_total_shoot = (sum_N_g_phloem_shoot + hz_df_MS.groupby(['t', 'plant', 'axis'])['N_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['N_g_total_tillers'].agg('sum')) N_content_shoot = sum_N_g_shoot / sum_dry_mass_shoot * 100 N_content_total_DM_shoot = sum_N_g_total_shoot / sum_dry_mass_total_shoot * 100 N_content_mstruct_shoot = sum_N_g_shoot / sum_mstruct_shoot * 100 N_content_roots = (N_content * sum_dry_mass - N_content_shoot * sum_dry_mass_shoot) / sum_dry_mass_roots N_content_mstruct_roots = (N_content_mstruct * sum_mstruct - N_content_mstruct_shoot * sum_mstruct_shoot) / sum_mstruct_roots # WSC hz_df_MS['WSC_g_tillers'] = hz_df_MS['WSC_g'] * hz_df_MS['nb_replications'] elt_df_MS['WSC_g_tillers'] = elt_df_MS['WSC_g'] * elt_df_MS['nb_replications'] WSC_g_plant = hz_df_MS.groupby(['t', 'plant', 'axis'])['WSC_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['WSC_g_tillers'].agg('sum') + \ pp_organs_df.groupby(['t', 'plant', 'axis'])['WSC_g'].agg('sum') sum_WSC_g_shoot = (sum_WSC_g_phloem_shoot + hz_df_MS.groupby(['t', 'plant', 'axis'])['WSC_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['WSC_g_tillers'].agg('sum')) sum_WSC_g_laminae = (sum_WSC_g_phloem_laminae + elt_df_MS[elt_df_MS.element == 'LeafElement1' ].groupby(['t', 'plant', 'axis'])['WSC_g_tillers'].agg('sum')) sum_WSC_g_stem = (sum_WSC_g_phloem_stem + hz_df_MS.groupby(['t', 'plant', 'axis'])['WSC_g_tillers'].agg('sum') + elt_df_MS[~(elt_df_MS.element == 'LeafElement1')].groupby(['t', 'plant', 'axis'])['WSC_g_tillers'].agg('sum')) sum_WSC_g_roots = (sum_WSC_g_phloem_roots + pp_organs_df[(organs_df['organ'] == 'roots')].groupby(['t', 'plant', 'axis'])['WSC_g'].agg('sum')) # C/N ratio hz_df_MS['C_g_tillers'] = hz_df_MS['C_g'] * hz_df_MS['nb_replications'] elt_df_MS['C_g_tillers'] = elt_df_MS['C_g'] * elt_df_MS['nb_replications'] sum_C_g = (organs_df[organs_df['axis'] == 'MS'].groupby(['t', 'plant', 'axis'])['C_g'].agg('sum') + hz_df_MS.groupby(['t', 'plant', 'axis'])['C_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['C_g_tillers'].agg('sum')) sum_C_g_shoot = (sum_C_g_phloem_shoot + hz_df_MS.groupby(['t', 'plant', 'axis'])['C_g_tillers'].agg('sum') + elt_df_MS.groupby(['t', 'plant', 'axis'])['C_g_tillers'].agg('sum')) C_N_ratio = sum_C_g / sum_N_g C_N_ratio_shoot = sum_C_g_shoot / sum_N_g_shoot # C non structural sum_NSC_g = sum_C_g.values - (axes_df['mstruct'] * cnwheat_model.EcophysiologicalConstants.RATIO_C_mstruct) # Photosyntheses elements_df['Tillers_Photosynthesis'] = elements_df['Photosynthesis'] * elements_df['nb_replications'] elements_df['Tillers_Photosynthesis_An'] = elements_df['An'] * elements_df['green_area'] * 3600 * elements_df['nb_replications'] tillers_photosynthesis = elements_df[elements_df['axis'] == 'MS'].groupby(['t', 'plant', 'axis'])['Tillers_Photosynthesis'].agg('sum') # TEMPORARY : porter au niveau de la plante tillers_photosynthesis_An = elements_df[elements_df['axis'] == 'MS'].groupby(['t', 'plant', 'axis'])['Tillers_Photosynthesis_An'].agg('sum') tot_photosynthesis = elements_df[elements_df['axis'] == 'MS'].groupby(['t', 'plant', 'axis'])['Photosynthesis'].agg('sum') # INN DM_t_ha = sum_dry_mass_shoot * 250 * 10 ** -2 # convert from g.plant-1 to t.ha-1 N_content_critical = np.where(DM_t_ha < 1.55, 4.4, 5.35 * DM_t_ha ** -0.442) # from Justes 1994 : valid at field scale from Feekes 3 i.e. mid tillering NNI = N_content_shoot / N_content_critical # Ratio Non Structural Mass NS_shoot = (1 - sum_mstruct_shoot / sum_dry_mass_shoot) * 100 NS_stem = (1 - sum_mstruct_stem / sum_dry_mass_stem) * 100 NS_laminae = (1 - sum_mstruct_laminae / sum_dry_mass_laminae) * 100 NS_roots = (1 - sum_mstruct_roots / sum_dry_mass_roots) * 100 NS = (1 - sum_mstruct / sum_dry_mass) * 100 # C_respired_shoot hz_df_MS['Respi_growth_tillers'] = hz_df_MS['Respi_growth'].fillna(0) * hz_df_MS['nb_replications'].fillna(1) C_respired_shoot = pp_axes_df.sum_respi_shoot.fillna(0.) + hz_df_MS.groupby(AXES_T_INDEXES, as_index=False)['Respi_growth_tillers'].sum().Respi_growth_tillers # C_respired_roots C_respired_roots = pp_axes_df.sum_respi_roots.fillna(0.) + organs_df[(organs_df['organ'] == 'roots')]['Respi_growth'].reset_index(drop=True) # Add to axes df pp_axes_df.sort_values(AXES_T_INDEXES, inplace=True) # Make sure axes_df is sorted pp_axes_df.loc[:, 'C_N_ratio'] = C_N_ratio.values pp_axes_df.loc[:, 'C_N_ratio_shoot'] = C_N_ratio_shoot.values pp_axes_df.loc[:, 'N_content'] = N_content.values pp_axes_df.loc[:, 'N_content_shoot'] = N_content_shoot.values pp_axes_df.loc[:, 'N_content_roots'] = N_content_roots.values pp_axes_df.loc[:, 'N_content_mstruct'] = N_content_mstruct.values pp_axes_df.loc[:, 'N_content_mstruct_shoot'] = N_content_mstruct_shoot.values pp_axes_df.loc[:, 'N_content_total_DM_shoot'] = N_content_total_DM_shoot.values pp_axes_df.loc[:, 'N_content_mstruct_roots'] = N_content_mstruct_roots.values pp_axes_df.loc[:, 'sum_N_g'] = sum_N_g.values pp_axes_df.loc[:, 'sum_N_g_shoot'] = sum_N_g_shoot.values pp_axes_df.loc[:, 'sum_dry_mass'] = sum_dry_mass.values pp_axes_df.loc[:, 'sum_dry_mass_shoot'] = sum_dry_mass_shoot.values pp_axes_df.loc[:, 'sum_dry_mass_laminae'] = sum_dry_mass_laminae.values pp_axes_df.loc[:, 'sum_dry_mass_stem'] = sum_dry_mass_stem.values pp_axes_df.loc[:, 'sum_dry_mass_roots'] = sum_dry_mass_roots.values pp_axes_df.loc[:, 'sum_C_g'] = sum_C_g.values pp_axes_df.loc[:, 'sum_NSC_g'] = sum_NSC_g.values pp_axes_df.loc[:, 'dry_mass_phloem'] = sum_dry_mass_phloem.values pp_axes_df.loc[:, 'shoot_roots_ratio'] = pp_axes_df['sum_dry_mass_shoot'] / pp_axes_df['sum_dry_mass_roots'] pp_axes_df.loc[:, 'shoot_roots_mstruct_ratio'] = shoot_roots_mstruct_ratio.values pp_axes_df.loc[:, 'Total_Photosynthesis'] = tot_photosynthesis.values pp_axes_df.loc[:, 'Tillers_Photosynthesis'] = tillers_photosynthesis.values pp_axes_df.loc[:, 'Tillers_Photosynthesis_An'] = tillers_photosynthesis_An.values pp_axes_df.loc[:, 'NNI'] = NNI.values pp_axes_df.loc[:, 'NS_roots'] = NS_roots.values pp_axes_df.loc[:, 'NS_shoot'] = NS_shoot.values pp_axes_df.loc[:, 'NS_stem'] = NS_stem.values pp_axes_df.loc[:, 'NS_laminae'] = NS_laminae.values pp_axes_df.loc[:, 'NS'] = NS.values pp_axes_df.loc[:, 'mstruct_shoot'] = sum_mstruct_shoot.values pp_axes_df.loc[:, 'mstruct_laminae'] = sum_mstruct_laminae.values pp_axes_df.loc[:, 'mstruct_stem'] = sum_mstruct_stem.values pp_axes_df.loc[:, 'C_respired_shoot'] = C_respired_shoot pp_axes_df.loc[:, 'C_respired_roots'] = C_respired_roots pp_axes_df.loc[:, 'WSC_g'] = WSC_g_plant.values pp_axes_df.loc[:, 'Cont_WSC_DM'] = pp_axes_df['WSC_g'] / pp_axes_df['sum_dry_mass'] * 100 pp_axes_df.loc[:, 'Cont_WSC_DM_shoot'] = sum_WSC_g_shoot.values / sum_dry_mass_shoot.values * 100 pp_axes_df.loc[:, 'Cont_WSC_DM_laminae'] = sum_WSC_g_laminae.values / sum_dry_mass_laminae.values * 100 pp_axes_df.loc[:, 'Cont_WSC_DM_stem'] = sum_WSC_g_stem.values / sum_dry_mass_stem.values * 100 pp_axes_df.loc[:, 'Cont_WSC_DM_roots'] = sum_WSC_g_roots.values / sum_dry_mass_roots.values * 100 pp_axes_df = pp_axes_df.reindex(AXES_RUN_POSTPROCESSING_VARIABLES, axis=1, copy=False) pp_axes_df['plant'] = pp_axes_df['plant'].astype(int) returned_dataframes.append(pp_axes_df) else: returned_dataframes.append(pd.DataFrame({'A': []})) # soils if soils_df is not None: pp_soils_df = pd.concat([soils_df, pd.DataFrame(columns=SOILS_POSTPROCESSING_VARIABLES)]) pp_soils_df = pp_soils_df.reindex(columns=SOILS_RUN_POSTPROCESSING_VARIABLES, copy=False) pp_soils_df[['plant']] = pp_soils_df[['plant']].astype(int) returned_dataframes.append(pp_soils_df) else: returned_dataframes.append(pd.DataFrame({'A': []})) return tuple(returned_dataframes)
# ----------------------------------------------------------- # --------------- GRAPHS GENERATION FRONT-END --------------- # -- PLEASE USE THIS FUNCTION FOR THE GENERATION OF GRAPHS -- # -----------------------------------------------------------
[docs] def generate_graphs(axes_df=None, hiddenzones_df=None, organs_df=None, elements_df=None, soils_df=None, graphs_dirpath='.'): """ Generate graphs to validate the outputs of CN-Wheat, and save them in directory `graphs_dirpath`. :param pandas.DataFrame axes_df: CN-Wheat outputs and post-processing at axis scale (see :attr:`PLANTS_RUN_POSTPROCESSING_VARIABLES`) :param pandas.DataFrame hiddenzones_df: CN-Wheat outputs at hidden zone scale (see :attr:`HIDDENZONE_RUN_POSTPROCESSING_VARIABLES`) :param pandas.DataFrame organs_df: CN-Wheat outputs at organ scale (see :attr:`ORGANS_RUN_POSTPROCESSING_VARIABLES`) :param pandas.DataFrame elements_df: CN-Wheat outputs at element scale (see :attr:`ELEMENTS_RUN_POSTPROCESSING_VARIABLES`) :param pandas.DataFrame soils_df: CN-Wheat outputs at soil scale (see :attr:`SOILS_RUN_POSTPROCESSING_VARIABLES`) :param str graphs_dirpath: the path of the directory to save the generated graphs in """ x_name = 't' x_label = 'Time (Hour)' colors = ['blue', 'darkorange', 'green', 'red', 'darkviolet', 'gold', 'magenta', 'brown', 'darkcyan', 'grey', 'lime'] colors = colors + colors + colors + colors + colors # 1) Photosynthetic organs if elements_df is not None: elements_df = elements_df.loc[elements_df['mstruct'] != 0] graph_variables_ph_elements = {'Ag': u'Gross photosynthesis (µmol m$^{-2}$ s$^{-1}$)', 'Tr': u'Organ surfacic transpiration rate (mmol H$_{2}$0 m$^{-2}$ s$^{-1}$)', 'Transpiration': u'Organ transpiration rate (mmol H$_{2}$0 s$^{-1}$)', 'Ts': u'Temperature surface (°C)', 'Conc_TriosesP': u'[TriosesP] (µmol g$^{-1}$ mstruct)', 'Conc_Starch': u'[Starch] (µmol g$^{-1}$ mstruct)', 'Conc_Sucrose': u'[Sucrose] (µmol g$^{-1}$ mstruct)', 'Conc_Fructan': u'[Fructan] (µmol g$^{-1}$ mstruct)', 'Conc_Nitrates': u'[Nitrates] (µmol g$^{-1}$ mstruct)', 'Conc_Amino_Acids': u'[Amino_Acids] (µmol g$^{-1}$ mstruct)', 'Conc_Proteins': u'[Proteins] (g g$^{-1}$ mstruct)', 'Cont_Fructan_DM': u'Fructan content (% DM)', 'Cont_WSC_DM': u'WSC content (% DM)', 'Nitrates_import': u'Total nitrates imported (µmol h$^{-1}$)', 'Amino_Acids_import': u'Total amino acids imported (µmol N h$^{-1}$)', 'S_Amino_Acids': u'[Rate of amino acids synthesis] (µmol N g$^{-1}$ mstruct h$^{-1}$)', 'S_Proteins': u'Rate of protein synthesis (µmol N g$^{-1}$ mstruct h$^{-1}$)', 'D_Proteins': u'Rate of protein degradation (µmol N g$^{-1}$ mstruct h$^{-1}$)', 'Loading_Sucrose': u'Loading Sucrose (µmol C sucrose h$^{-1}$)', 'Loading_Amino_Acids': u'Loading Amino acids (µmol N amino acids h$^{-1}$)', 'green_area': u'Green area (m$^{2}$)', 'R_phloem_loading': u'Respiration phloem loading (µmol C h$^{-1}$)', 'R_Nnit_red': u'Respiration nitrate reduction (µmol C h$^{-1}$)', 'R_residual': u'Respiration residual (µmol C h$^{-1}$)', 'mstruct': u'Structural mass (g)', 'Nstruct': u'Structural N mass (g)', 'Conc_cytokinins': u'[cytokinins] (UA g$^{-1}$ mstruct)', 'D_cytokinins': u'Cytokinin degradation (UA g$^{-1}$ mstruct)', 'cytokinins_import': u'Cytokinin import (UA)', 'Surfacic_NS': u'Surfacic Non Structural mass (g m$^{-2}$)', 'NS': u'Ratio of Non Structural mass', 'N_content': u'N content in the green tissues (% DM)', 'N_content_total_DM': u'N content in the green + senesced tissues (% DM)', 'N_tot': u'N mass (g)', 'SLA': u'Specific Leaf Area (m$^{2}$.kg$^{-1}$)', 'SLN': u'Surfacic Leaf Nitrogen (g.m$^{-2}$)', 'SLN_nonstruct': u'Surfacic Leaf Non-structural Nitrogen (g.m$^{-2}$)', 'length': u'Length (m)', 'Photosynthetic_efficiency': u'Photosynthetic yield (µmol C/µmol PARa)'} for org_ph in (['blade'], ['sheath'], ['internode'], ['peduncle', 'ear']): for variable_name, variable_label in graph_variables_ph_elements.items(): graph_name = variable_name + '_' + '_'.join(org_ph) + '.PNG' cnwheat_tools.plot_cnwheat_ouputs(elements_df, x_name=x_name, y_name=variable_name, x_label=x_label, y_label=variable_label, colors=[colors[i - 1] for i in elements_df.metamer.unique().tolist()], filters={'organ': org_ph}, plot_filepath=os.path.join(graphs_dirpath, graph_name), explicit_label=False) # 2) Roots, grains and phloem if organs_df is not None: # 'R_growth': u'Growth respiration of roots (µmol C h$^{-1}$)', graph_variables_organs = {'Conc_Sucrose': u'[Sucrose] (µmol g$^{-1}$ mstruct)', 'Dry_Mass': 'Dry mass (g)', 'Conc_Nitrates': u'[Nitrates] (µmol g$^{-1}$ mstruct)', 'Conc_Amino_Acids': u'[Amino Acids] (µmol g$^{-1}$ mstruct)', 'Proteins_N_Mass': u'[N Proteins] (g)', 'Uptake_Nitrates': u'Nitrates uptake (µmol h$^{-1}$)', 'sucrose': u'Sucrose (µmol)', 'amino_acids': u'Amino Acids (µmol)', 'Unloading_Sucrose': u'Unloaded sucrose (µmol C g$^{-1}$ mstruct h$^{-1}$)', 'Unloading_Amino_Acids': u'Unloaded Amino Acids (µmol N AA g$^{-1}$ mstruct h$^{-1}$)', 'S_Amino_Acids': u'Rate of amino acids synthesis (µmol N g$^{-1}$ mstruct h$^{-1}$)', 'S_Proteins': u'Rate of protein synthesis (µmol N h$^{-1}$)', 'Export_Nitrates': u'Total export of nitrates (µmol N h$^{-1}$)', 'Export_Amino_Acids': u'Total export of Amino acids (µmol N h$^{-1}$)', 'R_Nnit_upt': u'Respiration nitrates uptake (µmol C h$^{-1}$)', 'R_Nnit_red': u'Respiration nitrate reduction (µmol C h$^{-1}$)', 'R_residual': u'Respiration residual (µmol C h$^{-1}$)', 'R_grain_growth_struct': u'Respiration grain structural growth (µmol C h$^{-1}$)', 'R_grain_growth_starch': u'Respiration grain starch growth (µmol C h$^{-1}$)', 'mstruct': u'Structural mass (g)', 'C_exudation': u'Carbon lost by root exudation (µmol C g$^{-1}$ mstruct h$^{-1}$', 'N_exudation': u'Nitrogen lost by root exudation (µmol N g$^{-1}$ mstruct h$^{-1}$', 'Conc_cytokinins': u'[cytokinins] (UA g$^{-1}$ mstruct)', 'S_cytokinins': u'Rate of cytokinins synthesis (UA g$^{-1}$ mstruct)', 'Export_cytokinins': 'Export of cytokinins from roots (UA h$^{-1}$)', 'HATS_LATS': u'Potential uptake (µmol h$^{-1}$)', 'regul_transpiration': u'Regulating transpiration function', 'senesced_mstruct': u'Cumulated senesced mstruct (g)', 'synthetized_mstruct': u'Cumulated synthetized mstruct (g)'} for org in (['roots'], ['grains'], ['phloem']): for variable_name, variable_label in graph_variables_organs.items(): graph_name = variable_name + '_' + '_'.join(org) + '.PNG' cnwheat_tools.plot_cnwheat_ouputs(organs_df, x_name=x_name, y_name=variable_name, x_label=x_label, y_label=variable_label, colors=['blue'], filters={'organ': org}, plot_filepath=os.path.join(graphs_dirpath, graph_name), explicit_label=False) # 3) Soil if soils_df is not None: _, (ax1) = plt.subplots(1) Conc_Nitrates_soil = soils_df['Conc_Nitrates_Soil'] * 14E-6 ax1.plot(soils_df['t'], Conc_Nitrates_soil) ax1.set_ylabel(u'[Nitrates] (g m$^{-3}$)') ax1.set_xlabel('Time from flowering (hour)') ax1.set_title = 'Conc Nitrates Soil' ax1.set_ylim(bottom=0) plt.savefig(os.path.join(graphs_dirpath, 'Conc_Nitrates_Soil.PNG'), format='PNG', bbox_inches='tight') plt.close() # 4) Hidden zones if hiddenzones_df is not None: graph_variables_hiddenzones = {'Conc_Sucrose': u'[Sucrose] (µmol g$^{-1}$ mstruct)', 'Conc_Amino_Acids': u'[Amino Acids] (µmol g$^{-1}$ mstruct)', 'Conc_Proteins': u'[Proteins] (g g$^{-1}$ mstruct)', 'Conc_Fructan': u'[Fructan] (µmol g$^{-1}$ mstruct)', 'Cont_Fructan_DM': u'Fructan content (% DM)', 'Cont_Proteins_DM': u'Protein content (% DM)', 'Cont_WSC_DM': u'WSC content (% DM)', 'Unloading_Sucrose': u'Rate of Sucrose unloading (µmol C h${-1}$)', 'Unloading_Amino_Acids': u'Rate of Amino_acids unloading (µmol N h${-1}$)', 'mstruct': u'Structural mass (g)', 'Nstruct': u'Structural N mass (g)', 'leaf_L': u'Leaf length in hz (m)', 'delta_leaf_L': u'delta of leaf length (m)', 'internode_L': u'Internode length in hz (m)', 'leaf_pseudostem_length': u'leaf pseudostem length (m)'} for variable_name, variable_label in graph_variables_hiddenzones.items(): graph_name = variable_name + '_hz' + '.PNG' cnwheat_tools.plot_cnwheat_ouputs(hiddenzones_df, x_name=x_name, y_name=variable_name, x_label=x_label, y_label=variable_label, colors=[colors[i - 1] for i in hiddenzones_df.metamer.unique().tolist()], filters={'plant': 1, 'axis': 'MS'}, plot_filepath=os.path.join(graphs_dirpath, graph_name), explicit_label=False) # 4) Axes graph_variables_axes = {'mstruct': 'Axis mstruct (g)', 'C_N_ratio': u'C/N mass ratio', 'C_N_ratio_shoot': u'C/N mass ratio of the shoot', 'N_content': u'N content in the axis (% DM)', 'N_content_shoot': u'N content in the shoot (% DM)', 'N_content_total_DM_shoot': u'N content in the shoot acounting for partly senesced leaves (% DM)', 'N_content_roots': u'N content in the roots (% DM)', 'N_content_mstruct': u'N content in the axis (% mstruct)', 'N_content_mstruct_shoot': u'N content in the shoot (% mstruct)', 'N_content_mstruct_roots': u'N content in the roots (% mstruct)', 'sum_N_g': u'N mass (g)', 'sum_N_g_shoot': u'N mass in the shoot (g)', 'shoot_roots_ratio': u'Shoot/Roots dry mass ratio', 'shoot_roots_mstruct_ratio': u'Shoot/Roots mstruct ratio', 'sum_dry_mass': u'Total dry mass (g)', 'sum_dry_mass_shoot': u'Dry mass of the shoot (g)', 'sum_dry_mass_roots': u'Dry mass of the roots (g)', 'dry_mass_phloem': u'Dry mass of the phloem (g)', 'NNI': u'Nitrogen Nutrition Index', 'NS_shoot': u'Ratio of Non Structural Mass in the shoot', 'NS_roots': u'Ratio of Non Structural Mass in the roots', 'NS': u'Ratio of Non Structural Mass for the plant', 'mstruct_shoot': u'Structural Mass of the shoot (g)', 'Cont_WSC_DM': u'WSC content (% DM)'} for variable_name, variable_label in graph_variables_axes.items(): graph_name = variable_name + '_axis' + '.PNG' cnwheat_tools.plot_cnwheat_ouputs(axes_df, x_name=x_name, y_name=variable_name, x_label=x_label, y_label=variable_label, colors=['blue'], filters={'plant': 1, 'axis': 'MS'}, plot_filepath=os.path.join(graphs_dirpath, graph_name), explicit_label=False)