Source code for openalea.fspmwheat.fspmwheat_facade

# -*- coding: latin-1 -*-
from openalea.cnwheat import simulation as cnwheat_simulation
from openalea.elongwheat import simulation as elongwheat_simulation
from openalea.farquharwheat import converter as farquharwheat_converter
from openalea.growthwheat import simulation as growthwheat_simulation
from openalea.senescwheat import converter as senescwheat_converter
import numpy as np
import pandas as pd

"""
    fspmwheat.fspmwheat_facade
    ~~~~~~~~~~~~~~~~~~~~~~~~

    The module :mod:`fspmwheat.fspmwheat_facade` is a facade of the model FSPMWheat.

"""

#: columns which define the topology in the input/output dataframe
AXES_TOPOLOGY_COLUMNS = ['plant', 'axis']
ELEMENTS_TOPOLOGY_COLUMNS = ['plant', 'axis', 'metamer', 'organ', 'element']  # Mature + emerging elements
HIDDENZONES_TOPOLOGY_COLUMNS = ['plant', 'axis', 'metamer']
ORGANS_TOPOLOGY_COLUMNS = ['plant', 'axis', 'organ']
SOILS_TOPOLOGY_COLUMNS = ['plant', 'axis']

#: variables in each input/output dataframe
AXES_VARIABLES = set(cnwheat_simulation.Simulation.AXES_RUN_VARIABLES +
                     elongwheat_simulation.AXIS_INPUTS_OUTPUTS +
                     list(growthwheat_simulation.AXIS_INPUTS_OUTPUTS) +
                     senescwheat_converter.SENESCWHEAT_AXES_INPUTS_OUTPUTS)
ELEMENTS_VARIABLES = set(cnwheat_simulation.Simulation.ELEMENTS_RUN_VARIABLES +
                         elongwheat_simulation.ELEMENT_INPUTS_OUTPUTS +
                         list(farquharwheat_converter.FARQUHARWHEAT_ELEMENTS_INPUTS_OUTPUTS) +
                         list(growthwheat_simulation.ELEMENT_INPUTS_OUTPUTS) +
                         senescwheat_converter.SENESCWHEAT_ELEMENTS_INPUTS_OUTPUTS)
HIDDENZONES_VARIABLES = set(cnwheat_simulation.Simulation.HIDDENZONE_RUN_VARIABLES +
                            elongwheat_simulation.HIDDENZONE_INPUTS_OUTPUTS +
                            list(growthwheat_simulation.HIDDENZONE_INPUTS_OUTPUTS))
ORGANS_VARIABLES = set(cnwheat_simulation.Simulation.ORGANS_RUN_VARIABLES +
                       list(growthwheat_simulation.ROOT_INPUTS_OUTPUTS) +
                       senescwheat_converter.SENESCWHEAT_ROOTS_INPUTS_OUTPUTS)
SOILS_VARIABLES = set(cnwheat_simulation.Simulation.SOILS_RUN_VARIABLES)

BOTANICAL_ORGANS_AT_AXIS_SCALE = ['roots', 'phloem', 'grains']
BOTANICAL_COMPARTMENTS_AT_AXIS_SCALE = BOTANICAL_ORGANS_AT_AXIS_SCALE + ['soil']


[docs] class FSPMWheatFacade(object): """ The FSPMWheatFacade class permits to ... from a :class:`MTG <openalea.mtg.mtg.MTG>`, and update the MTG and the dataframes shared between all models. """ def __init__(self, shared_mtg): # shared_axes_inputs_outputs_df, # shared_organs_inputs_outputs_df, # shared_hiddenzones_inputs_outputs_df, # shared_elements_inputs_outputs_df, # shared_soils_inputs_outputs_df, # update_shared_df = True): """ :param openalea.mtg.mtg.MTG shared_mtg: The MTG shared between all models. :param pandas.DataFrame shared_axes_inputs_outputs_df: the dataframe of inputs and outputs at axes scale shared between all models. :param pandas.DataFrame shared_organs_inputs_outputs_df: the dataframe of inputs and outputs at organs scale shared between all models. :param pandas.DataFrame shared_hiddenzones_inputs_outputs_df: the dataframe of inputs and outputs at hiddenzones scale shared between all models. :param pandas.DataFrame shared_elements_inputs_outputs_df: the dataframe of inputs and outputs at elements scale shared between all models. :param pandas.DataFrame shared_soils_inputs_outputs_df: the dataframe of inputs and outputs at soils scale shared between all models. :param bool update_shared_df: If `True` update the shared dataframes at init and at each run (unless stated otherwise) """ self._shared_mtg = shared_mtg #: the MTG shared between all models # self._shared_axes_inputs_outputs_df = shared_axes_inputs_outputs_df #: the dataframe at axes scale shared between all models # self._shared_organs_inputs_outputs_df = shared_organs_inputs_outputs_df #: the dataframe at organs scale shared between all models # self._shared_hiddenzones_inputs_outputs_df = shared_hiddenzones_inputs_outputs_df #: the dataframe at hiddenzones scale shared between all models # self._shared_elements_inputs_outputs_df = shared_elements_inputs_outputs_df #: the dataframe at elements scale shared between all models # self._shared_soils_inputs_outputs_df = shared_soils_inputs_outputs_df #: the dataframe at soils scale shared between all models # self._update_shared_df = update_shared_df # if self._update_shared_df: # self._update_shared_dataframes(cnwheat_organs_data_df=model_organs_inputs_df, # cnwheat_hiddenzones_data_df=model_hiddenzones_inputs_df, # cnwheat_elements_data_df=model_elements_inputs_df, # cnwheat_soils_data_df=model_soils_inputs_df) def _read_outputs_on_MTG(self): """ Extract the outputs of all sub-models from the MTG shared between all models. """ axes_dict = {} elements_dict = {} hiddenzones_dict = {} organs_dict = {} soils_dict = {} for mtg_plant_vid in self._shared_mtg.components_iter(self._shared_mtg.root): mtg_plant_index = int(self._shared_mtg.index(mtg_plant_vid)) # Axis scale for mtg_axis_vid in self._shared_mtg.components_iter(mtg_plant_vid): mtg_axis_label = self._shared_mtg.label(mtg_axis_vid) mtg_axis_properties = self._shared_mtg.get_vertex_property(mtg_axis_vid) axis_id = (mtg_plant_index, mtg_axis_label) axis_dict = {} if mtg_axis_properties.get('nb_leaves') is None: continue for axis_run_variable in AXES_VARIABLES: if axis_run_variable in mtg_axis_properties: # use the input from the MTG axis_dict[axis_run_variable] = mtg_axis_properties[axis_run_variable] axes_dict[axis_id] = axis_dict # Botanical organs at axis scale for botanical_organ_name in BOTANICAL_ORGANS_AT_AXIS_SCALE: if botanical_organ_name in mtg_axis_properties: organ_id = (mtg_plant_index, mtg_axis_label, botanical_organ_name) mtg_organ_properties = mtg_axis_properties[botanical_organ_name] if mtg_organ_properties.get('sucrose') is None: continue organ_dict = {} for organ_run_variable in ORGANS_VARIABLES: if organ_run_variable in mtg_organ_properties: organ_dict[organ_run_variable] = mtg_organ_properties[organ_run_variable] organs_dict[organ_id] = organ_dict # Soil at axis scale if 'soil' in mtg_axis_properties: mtg_soil_properties = mtg_axis_properties['soil'] soil_dict = {} for soil_run_variable in SOILS_VARIABLES: if soil_run_variable in mtg_soil_properties: soil_dict[soil_run_variable] = mtg_soil_properties[soil_run_variable] soils_dict[axis_id] = soil_dict # Metamer scale for mtg_metamer_vid in self._shared_mtg.components_iter(mtg_axis_vid): mtg_metamer_index = int(self._shared_mtg.index(mtg_metamer_vid)) mtg_metamer_properties = self._shared_mtg.get_vertex_property(mtg_metamer_vid) if 'hiddenzone' in mtg_metamer_properties: hiddenzone_id = (mtg_plant_index, mtg_axis_label, mtg_metamer_index) mtg_hiddenzone_properties = mtg_metamer_properties['hiddenzone'] hiddenzone_dict = {} for hiddenzone_run_variable in HIDDENZONES_VARIABLES: if hiddenzone_run_variable in mtg_hiddenzone_properties: # use the input from the MTG hiddenzone_dict[hiddenzone_run_variable] = mtg_hiddenzone_properties[hiddenzone_run_variable] hiddenzones_dict[hiddenzone_id] = hiddenzone_dict # Photosynthetic organ scale for mtg_organ_vid in self._shared_mtg.components_iter(mtg_metamer_vid): mtg_organ_label = self._shared_mtg.label(mtg_organ_vid) # Element scale for mtg_element_vid in self._shared_mtg.components_iter(mtg_organ_vid): mtg_element_label = self._shared_mtg.label(mtg_element_vid) mtg_element_properties = self._shared_mtg.get_vertex_property(mtg_element_vid) if np.nan_to_num(self._shared_mtg.property('length').get(mtg_element_vid, 0)) == 0: continue element_dict = {} for elongwheat_element_run_variable in ELEMENTS_VARIABLES: element_dict[elongwheat_element_run_variable] = mtg_element_properties.get(elongwheat_element_run_variable, np.nan) element_id = (mtg_plant_index, mtg_axis_label, mtg_metamer_index, mtg_organ_label, mtg_element_label) elements_dict[element_id] = element_dict return {'axes': axes_dict, 'elements': elements_dict, 'hiddenzones': hiddenzones_dict, 'organs': organs_dict, 'soils': soils_dict} @staticmethod def _to_dataframes(data_dict): """ Convert outputs from _read_outputs_on_MTG() which are dictionaries to Pandas dataframes. :param dict data_dict: outputs from _read_outputs_on_MTG() which are dictionaries :return: Five dataframes: axes, elements, hiddenzones, organs, soils :rtype: (pandas.DataFrame, pandas.DataFrame, pandas.DataFrame, pandas.DataFrame, pandas.DataFrame) """ dataframes_dict = {} for (current_key, current_topology_columns, current_outputs_names) in (('soils', SOILS_TOPOLOGY_COLUMNS, SOILS_VARIABLES), ('organs', ORGANS_TOPOLOGY_COLUMNS, ORGANS_VARIABLES), ('hiddenzones', HIDDENZONES_TOPOLOGY_COLUMNS, HIDDENZONES_VARIABLES), ('elements', ELEMENTS_TOPOLOGY_COLUMNS, ELEMENTS_VARIABLES), ('axes', AXES_TOPOLOGY_COLUMNS, AXES_VARIABLES)): current_data_dict = data_dict[current_key] current_ids_df = pd.DataFrame(current_data_dict.keys(), columns=current_topology_columns) current_data_df = pd.DataFrame(current_data_dict.values()) current_df = pd.concat([current_ids_df, current_data_df], axis=1) current_df.sort_values(by=current_topology_columns, inplace=True) current_columns_sorted = current_topology_columns + list(current_outputs_names) current_df = current_df.reindex(current_columns_sorted, axis=1, copy=False) # Reset dtypes current_df = pd.DataFrame(current_df.where(current_df.notnull(), np.nan).values.tolist(), columns=current_df.columns) current_df.reset_index(drop=True, inplace=True) dataframes_dict[current_key] = current_df return dataframes_dict['axes'], dataframes_dict['elements'], dataframes_dict['hiddenzones'], dataframes_dict['organs'], dataframes_dict['soils']
[docs] def build_outputs_df_from_MTG(self): outputs_dict = self._read_outputs_on_MTG() return self._to_dataframes(outputs_dict)