Пример #1
0
    def __init__(self,
                 shared_mtg,
                 delta_t,
                 culm_density,
                 model_organs_inputs_df,
                 model_hiddenzones_inputs_df,
                 model_elements_inputs_df,
                 model_soils_inputs_df,
                 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_parameters=None):
        """
        :param openalea.mtg.mtg.MTG shared_mtg: The MTG shared between all models.
        :param int delta_t: The delta between two runs, in seconds.
        :param dict culm_density: The density of culm. One key per plant.
        :param pandas.DataFrame model_organs_inputs_df: the inputs of the model at organs scale.
        :param pandas.DataFrame model_hiddenzones_inputs_df: the inputs of the model at hiddenzones scale.
        :param pandas.DataFrame model_elements_inputs_df: the inputs of the model at elements scale.
        :param pandas.DataFrame model_soils_inputs_df: the inputs of the model at soils scale.
        :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 dict or None update_parameters: A dictionary with the parameters to update, should have the form {'Organ_label1': {'param1': value1, 'param2': value2}, ...}.
        """

        self._shared_mtg = shared_mtg  #: the MTG shared between all models

        self._simulation = cnwheat_simulation.Simulation(
            respiration_model=respiwheat_model,
            delta_t=delta_t,
            culm_density=culm_density)

        self.population, self.soils = cnwheat_converter.from_dataframes(
            model_organs_inputs_df, model_hiddenzones_inputs_df,
            model_elements_inputs_df, model_soils_inputs_df)

        self._update_parameters = update_parameters

        self._simulation.initialize(self.population, self.soils)

        self._update_shared_MTG()

        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_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)
Пример #2
0
def test_simulation_run(overwrite_desired_data=False):
    """Test the run of a simulation, without interpolation of the forcings."""

    TEST_DIR_PATH = 'simulation_run'

    # Inputs of the test
    INPUTS_DIRPATH = os.path.join(TEST_DIR_PATH, 'inputs')
    ORGANS_INITIAL_STATE_FILENAME = 'organs_initial_state.csv'
    HIDDENZONES_INITIAL_STATE_FILENAME = 'hiddenzones_initial_state.csv'
    ELEMENTS_INITIAL_STATE_FILENAME = 'elements_initial_state.csv'
    SOILS_INITIAL_STATE_FILENAME = 'soils_initial_state.csv'
    ELEMENTS_PHOTOSYNTHESIS_FORCINGS_FILENAME = 'elements_photosynthesis_forcings.csv'
    ROOTS_SENESCENCE_FORCINGS_FILENAME = 'roots_senescence_forcings.csv'
    ELEMENTS_SENESCENCE_FORCINGS_FILENAME = 'elements_senescence_forcings.csv'

    # Outputs of the test
    OUTPUTS_DIRPATH = os.path.join(TEST_DIR_PATH, 'outputs')
    DESIRED_AXES_OUTPUTS_FILENAME = 'desired_axes_outputs.csv'
    DESIRED_ORGANS_OUTPUTS_FILENAME = 'desired_organs_outputs.csv'
    DESIRED_HIDDENZONES_OUTPUTS_FILENAME = 'desired_hiddenzones_outputs.csv'
    DESIRED_ELEMENTS_OUTPUTS_FILENAME = 'desired_elements_outputs.csv'
    DESIRED_SOILS_OUTPUTS_FILENAME = 'desired_soils_outputs.csv'
    ACTUAL_AXES_OUTPUTS_FILENAME = 'actual_axes_outputs.csv'
    ACTUAL_ORGANS_OUTPUTS_FILENAME = 'actual_organs_outputs.csv'
    ACTUAL_HIDDENZONES_OUTPUTS_FILENAME = 'actual_hiddenzones_outputs.csv'
    ACTUAL_ELEMENTS_OUTPUTS_FILENAME = 'actual_elements_outputs.csv'
    ACTUAL_SOILS_OUTPUTS_FILENAME = 'actual_soils_outputs.csv'

    # Simulation parameters
    START_TIME = 0
    SIMULATION_LENGTH = 48
    TIME_STEP = 1
    CULM_DENSITY = {1: 410}

    time_step_seconds = TIME_STEP * HOUR_TO_SECOND_CONVERSION_FACTOR

    # Read the inputs from CSV files and create inputs dataframes
    inputs_dataframes = {}
    for inputs_filename in (ORGANS_INITIAL_STATE_FILENAME,
                            HIDDENZONES_INITIAL_STATE_FILENAME,
                            ELEMENTS_INITIAL_STATE_FILENAME,
                            SOILS_INITIAL_STATE_FILENAME):
        inputs_dataframes[inputs_filename] = pd.read_csv(
            os.path.join(INPUTS_DIRPATH, inputs_filename))

    # Convert the inputs dataframes to a population of plants and a dictionary of soils
    population, soils = cnwheat_converter.from_dataframes(
        inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME],
        inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME],
        inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME],
        inputs_dataframes[SOILS_INITIAL_STATE_FILENAME])

    # Create the simulation
    simulation_ = cnwheat_simulation.Simulation(
        respiration_model=respiwheat_model,
        delta_t=time_step_seconds,
        culm_density=CULM_DENSITY)

    # Initialize the simulation from the population of plants and the dictionary of soils created previously
    simulation_.initialize(population, soils)

    # Read photosynthesis and senescence forcings from CSV files, create dataframes, and group the dataframes by object index
    photosynthesis_elements_data_filepath = os.path.join(
        INPUTS_DIRPATH, ELEMENTS_PHOTOSYNTHESIS_FORCINGS_FILENAME)
    photosynthesis_elements_data_df = pd.read_csv(
        photosynthesis_elements_data_filepath)
    photosynthesis_elements_data_grouped = photosynthesis_elements_data_df.groupby(
        cnwheat_simulation.Simulation.ELEMENTS_T_INDEXES)
    senescence_roots_data_filepath = os.path.join(
        INPUTS_DIRPATH, ROOTS_SENESCENCE_FORCINGS_FILENAME)
    senescence_roots_data_df = pd.read_csv(senescence_roots_data_filepath)
    senescence_roots_data_grouped = senescence_roots_data_df.groupby(
        cnwheat_simulation.Simulation.AXES_T_INDEXES)
    senescence_elements_data_filepath = os.path.join(
        INPUTS_DIRPATH, ELEMENTS_SENESCENCE_FORCINGS_FILENAME)
    senescence_elements_data_df = pd.read_csv(
        senescence_elements_data_filepath)
    senescence_elements_data_grouped = senescence_elements_data_df.groupby(
        cnwheat_simulation.Simulation.ELEMENTS_T_INDEXES)

    # Force the senescence and photosynthesis of the population
    force_senescence_and_photosynthesis(0, population,
                                        senescence_roots_data_grouped,
                                        senescence_elements_data_grouped,
                                        photosynthesis_elements_data_grouped)

    # Reinitialize the simulation from forced population and soils
    simulation_.initialize(population, soils)

    # Define the time grid of the simulation
    time_grid = range(START_TIME, SIMULATION_LENGTH + TIME_STEP, TIME_STEP)

    # Create empty lists of dataframes to store the outputs at each step of the simulation
    axes_outputs_df_list = []
    organs_outputs_df_list = []
    hiddenzones_outputs_df_list = []
    elements_outputs_df_list = []
    soils_outputs_df_list = []

    for t in time_grid:

        if t > 0:
            # Run the model of CN exchanges ; the population is internally updated by the model
            simulation_.run()

        # Convert the model outputs to dataframes
        _, axes_outputs_df, _, organs_outputs_df, hiddenzones_outputs_df, elements_outputs_df, soils_outputs_df = cnwheat_converter.to_dataframes(
            simulation_.population, simulation_.soils)

        # Append the outputs dataframes at current t to the global lists of dataframes
        for df, list_ in ((axes_outputs_df, axes_outputs_df_list),
                          (organs_outputs_df, organs_outputs_df_list),
                          (hiddenzones_outputs_df,
                           hiddenzones_outputs_df_list),
                          (elements_outputs_df, elements_outputs_df_list),
                          (soils_outputs_df, soils_outputs_df_list)):
            df.insert(0, 't', t)
            list_.append(df)

        if 0 < t < SIMULATION_LENGTH:
            # Force the senescence and photosynthesis of the population
            force_senescence_and_photosynthesis(
                t, population, senescence_roots_data_grouped,
                senescence_elements_data_grouped,
                photosynthesis_elements_data_grouped)
            # Reinitialize the simulation from forced population and soils
            simulation_.initialize(population, soils)

    # compare actual to desired outputs at each scale level (an exception is raised if the test failed)
    for (outputs_df_list,
         desired_outputs_filename,
         actual_outputs_filename,
         state_variables_names) \
            in ((axes_outputs_df_list, DESIRED_AXES_OUTPUTS_FILENAME, ACTUAL_AXES_OUTPUTS_FILENAME,
                 cnwheat_simulation.Simulation.AXES_T_INDEXES + cnwheat_simulation.Simulation.AXES_STATE),
                (organs_outputs_df_list, DESIRED_ORGANS_OUTPUTS_FILENAME, ACTUAL_ORGANS_OUTPUTS_FILENAME,
                 cnwheat_simulation.Simulation.ORGANS_T_INDEXES + cnwheat_simulation.Simulation.ORGANS_STATE),
                (hiddenzones_outputs_df_list, DESIRED_HIDDENZONES_OUTPUTS_FILENAME,
                 ACTUAL_HIDDENZONES_OUTPUTS_FILENAME,
                 cnwheat_simulation.Simulation.HIDDENZONE_T_INDEXES + cnwheat_simulation.Simulation.HIDDENZONE_STATE),
                (elements_outputs_df_list, DESIRED_ELEMENTS_OUTPUTS_FILENAME, ACTUAL_ELEMENTS_OUTPUTS_FILENAME,
                 cnwheat_simulation.Simulation.ELEMENTS_T_INDEXES + cnwheat_simulation.Simulation.ELEMENTS_STATE),
                (soils_outputs_df_list, DESIRED_SOILS_OUTPUTS_FILENAME, ACTUAL_SOILS_OUTPUTS_FILENAME,
                 cnwheat_simulation.Simulation.SOILS_T_INDEXES + cnwheat_simulation.Simulation.SOILS_STATE)):
        outputs_df = pd.concat(outputs_df_list, ignore_index=True)
        outputs_df = outputs_df.loc[:,
                                    state_variables_names]  # compare only the values of the compartments
        cnwheat_tools.compare_actual_to_desired(
            OUTPUTS_DIRPATH,
            outputs_df,
            desired_outputs_filename,
            actual_outputs_filename,
            precision=PRECISION,
            overwrite_desired_data=overwrite_desired_data)
Пример #3
0
def test_simulation_logging(overwrite_desired_data=False):
    """Test the logging of a simulation."""

    TEST_DIR_PATH = 'simulation_logging'

    # Inputs of the test
    INPUTS_DIRPATH = os.path.join(TEST_DIR_PATH, 'inputs')
    ORGANS_INITIAL_STATE_FILENAME = 'organs_initial_state.csv'
    HIDDENZONES_INITIAL_STATE_FILENAME = 'hiddenzones_initial_state.csv'
    ELEMENTS_INITIAL_STATE_FILENAME = 'elements_initial_state.csv'
    SOILS_INITIAL_STATE_FILENAME = 'soils_initial_state.csv'
    ELEMENTS_PHOTOSYNTHESIS_FORCINGS_FILENAME = 'elements_photosynthesis_forcings.csv'
    ROOTS_SENESCENCE_FORCINGS_FILENAME = 'roots_senescence_forcings.csv'
    ELEMENTS_SENESCENCE_FORCINGS_FILENAME = 'elements_senescence_forcings.csv'

    # Outputs of the test
    LOGS_DIRPATH = os.path.join(TEST_DIR_PATH, 'logs')
    DESIRED_AXES_COMPARTMENTS_FILENAME = 'desired_axes_compartments.csv'
    DESIRED_ORGANS_COMPARTMENTS_FILENAME = 'desired_organs_compartments.csv'
    DESIRED_HIDDENZONES_COMPARTMENTS_FILENAME = 'desired_hiddenzones_compartments.csv'
    DESIRED_ELEMENTS_COMPARTMENTS_FILENAME = 'desired_elements_compartments.csv'
    DESIRED_SOILS_COMPARTMENTS_FILENAME = 'desired_soils_compartments.csv'
    DESIRED_AXES_DERIVATIVES_FILENAME = 'desired_axes_derivatives.csv'
    DESIRED_ORGANS_DERIVATIVES_FILENAME = 'desired_organs_derivatives.csv'
    DESIRED_HIDDENZONES_DERIVATIVES_FILENAME = 'desired_hiddenzones_derivatives.csv'
    DESIRED_ELEMENTS_DERIVATIVES_FILENAME = 'desired_elements_derivatives.csv'
    DESIRED_SOILS_DERIVATIVES_FILENAME = 'desired_soils_derivatives.csv'
    ACTUAL_AXES_COMPARTMENTS_FILENAME = 'actual_axes_compartments.csv'
    ACTUAL_ORGANS_COMPARTMENTS_FILENAME = 'actual_organs_compartments.csv'
    ACTUAL_HIDDENZONES_COMPARTMENTS_FILENAME = 'actual_hiddenzones_compartments.csv'
    ACTUAL_ELEMENTS_COMPARTMENTS_FILENAME = 'actual_elements_compartments.csv'
    ACTUAL_SOILS_COMPARTMENTS_FILENAME = 'actual_soils_compartments.csv'
    ACTUAL_AXES_DERIVATIVES_FILENAME = 'actual_axes_derivatives.csv'
    ACTUAL_ORGANS_DERIVATIVES_FILENAME = 'actual_organs_derivatives.csv'
    ACTUAL_HIDDENZONES_DERIVATIVES_FILENAME = 'actual_hiddenzones_derivatives.csv'
    ACTUAL_ELEMENTS_DERIVATIVES_FILENAME = 'actual_elements_derivatives.csv'
    ACTUAL_SOILS_DERIVATIVES_FILENAME = 'actual_soils_derivatives.csv'

    # Config file path for logging
    LOGGING_CONFIG_FILEPATH = os.path.join(TEST_DIR_PATH, 'logging.json')

    # Simulation parameters
    START_TIME = 0
    SIMULATION_LENGTH = 5
    TIME_STEP = 1
    CULM_DENSITY = {1: 410}

    time_step_seconds = TIME_STEP * HOUR_TO_SECOND_CONVERSION_FACTOR

    # Remove actual logs files
    for logs_file in glob.glob(os.path.join(LOGS_DIRPATH, "actual*.csv")):
        os.remove(logs_file)

    # Setup the logging (without removing the desired logs since we need them for the comparison test)
    cnwheat_tools.setup_logging(config_filepath=LOGGING_CONFIG_FILEPATH,
                                level=logging.DEBUG,
                                log_model=True,
                                log_compartments=True,
                                log_derivatives=True,
                                remove_old_logs=False)

    # Read the inputs from CSV files and create inputs dataframes
    inputs_dataframes = {}
    for inputs_filename in (ORGANS_INITIAL_STATE_FILENAME,
                            HIDDENZONES_INITIAL_STATE_FILENAME,
                            ELEMENTS_INITIAL_STATE_FILENAME,
                            SOILS_INITIAL_STATE_FILENAME):
        inputs_dataframes[inputs_filename] = pd.read_csv(
            os.path.join(INPUTS_DIRPATH, inputs_filename))

    # Convert the inputs dataframes to a population of plants and a dictionary of soils
    population, soils = cnwheat_converter.from_dataframes(
        inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME],
        inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME],
        inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME],
        inputs_dataframes[SOILS_INITIAL_STATE_FILENAME])

    # Create the simulation
    simulation_ = cnwheat_simulation.Simulation(
        respiration_model=respiwheat_model,
        delta_t=time_step_seconds,
        culm_density=CULM_DENSITY)

    # Initialize the simulation from the population of plants and the dictionary of soils created previously
    simulation_.initialize(population, soils)

    # Read photosynthesis and senescence forcings from CSV files, create dataframes, and group the dataframes by object index
    photosynthesis_elements_data_filepath = os.path.join(
        INPUTS_DIRPATH, ELEMENTS_PHOTOSYNTHESIS_FORCINGS_FILENAME)
    photosynthesis_elements_data_df = pd.read_csv(
        photosynthesis_elements_data_filepath)
    photosynthesis_elements_data_grouped = photosynthesis_elements_data_df.groupby(
        cnwheat_simulation.Simulation.ELEMENTS_T_INDEXES)
    senescence_roots_data_filepath = os.path.join(
        INPUTS_DIRPATH, ROOTS_SENESCENCE_FORCINGS_FILENAME)
    senescence_roots_data_df = pd.read_csv(senescence_roots_data_filepath)
    senescence_roots_data_grouped = senescence_roots_data_df.groupby(
        cnwheat_simulation.Simulation.AXES_T_INDEXES)
    senescence_elements_data_filepath = os.path.join(
        INPUTS_DIRPATH, ELEMENTS_SENESCENCE_FORCINGS_FILENAME)
    senescence_elements_data_df = pd.read_csv(
        senescence_elements_data_filepath)
    senescence_elements_data_grouped = senescence_elements_data_df.groupby(
        cnwheat_simulation.Simulation.ELEMENTS_T_INDEXES)

    # Force the senescence and photosynthesis of the population
    force_senescence_and_photosynthesis(0, population,
                                        senescence_roots_data_grouped,
                                        senescence_elements_data_grouped,
                                        photosynthesis_elements_data_grouped)

    # Reinitialize the simulation from forced population and soils
    simulation_.initialize(population, soils)

    # Define the time grid of the simulation
    time_grid = range(START_TIME, SIMULATION_LENGTH + TIME_STEP, TIME_STEP)

    # Create empty lists of dataframes to store the outputs at each step of the simulation
    axes_outputs_df_list = []
    organs_outputs_df_list = []
    hiddenzones_outputs_df_list = []
    elements_outputs_df_list = []
    soils_outputs_df_list = []

    for t in time_grid:

        if t > 0:
            # Run the model of CN exchanges ; the population is internally updated by the model
            simulation_.run()

        # Convert the model outputs to dataframes
        _, axes_outputs_df, _, organs_outputs_df, hiddenzones_outputs_df, elements_outputs_df, soils_outputs_df = cnwheat_converter.to_dataframes(
            simulation_.population, simulation_.soils)

        # Append the outputs dataframes at current t to the global lists of dataframes
        for df, list_ in ((axes_outputs_df, axes_outputs_df_list),
                          (organs_outputs_df, organs_outputs_df_list),
                          (hiddenzones_outputs_df,
                           hiddenzones_outputs_df_list),
                          (elements_outputs_df, elements_outputs_df_list),
                          (soils_outputs_df, soils_outputs_df_list)):
            df.insert(0, 't', t)
            list_.append(df)

        if 0 < t < SIMULATION_LENGTH:
            # Force the senescence and photosynthesis of the population
            force_senescence_and_photosynthesis(
                t, population, senescence_roots_data_grouped,
                senescence_elements_data_grouped,
                photosynthesis_elements_data_grouped)
            # Reinitialize the simulation from forced population and soils
            simulation_.initialize(population, soils)

    # compare actual to desired logs at each scale level (an exception is raised if the test failed)
    # Compartments logs
    for (desired_compartments_filename,
         actual_compartments_filename) \
            in ((DESIRED_AXES_COMPARTMENTS_FILENAME, ACTUAL_AXES_COMPARTMENTS_FILENAME),
                (DESIRED_ORGANS_COMPARTMENTS_FILENAME, ACTUAL_ORGANS_COMPARTMENTS_FILENAME),
                (DESIRED_HIDDENZONES_COMPARTMENTS_FILENAME, ACTUAL_HIDDENZONES_COMPARTMENTS_FILENAME),
                (DESIRED_ELEMENTS_COMPARTMENTS_FILENAME, ACTUAL_ELEMENTS_COMPARTMENTS_FILENAME),
                (DESIRED_SOILS_COMPARTMENTS_FILENAME, ACTUAL_SOILS_COMPARTMENTS_FILENAME)):
        try:
            actual_compartments_df = pd.read_csv(
                os.path.join(LOGS_DIRPATH, actual_compartments_filename))
        except pd.errors.EmptyDataError:
            continue  # This file is empty: ignore it.
        cnwheat_tools.compare_actual_to_desired(
            LOGS_DIRPATH,
            actual_compartments_df,
            desired_compartments_filename,
            precision=PRECISION,
            overwrite_desired_data=overwrite_desired_data)
    # Derivatives logs
    for (desired_derivatives_filename,
         actual_derivatives_filename) \
            in ((DESIRED_AXES_DERIVATIVES_FILENAME, ACTUAL_AXES_DERIVATIVES_FILENAME),
                (DESIRED_ORGANS_DERIVATIVES_FILENAME, ACTUAL_ORGANS_DERIVATIVES_FILENAME),
                (DESIRED_HIDDENZONES_DERIVATIVES_FILENAME, ACTUAL_HIDDENZONES_DERIVATIVES_FILENAME),
                (DESIRED_ELEMENTS_DERIVATIVES_FILENAME, ACTUAL_ELEMENTS_DERIVATIVES_FILENAME),
                (DESIRED_SOILS_DERIVATIVES_FILENAME, ACTUAL_SOILS_DERIVATIVES_FILENAME)):
        try:
            actual_derivatives_df = pd.read_csv(
                os.path.join(LOGS_DIRPATH, actual_derivatives_filename))
        except pd.errors.EmptyDataError:
            continue  # This file is empty: ignore it.
        cnwheat_tools.compare_actual_to_desired(
            LOGS_DIRPATH,
            actual_derivatives_df,
            desired_derivatives_filename,
            precision=PRECISION,
            overwrite_desired_data=overwrite_desired_data)
Пример #4
0
        inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME],
        inputs_dataframes[SOILS_INITIAL_STATE_FILENAME])

    # Set simulation parameters for interpolation
    if INTERPOLATE_FORCINGS:
        senescence_forcings_delta_t = time_step_seconds
        photosynthesis_forcings_delta_t = time_step_seconds
    else:
        senescence_forcings_delta_t = None
        photosynthesis_forcings_delta_t = None

    # Create the simulation
    simulation_ = cnwheat_simulation.Simulation(
        respiration_model=respiwheat_model,
        delta_t=time_step_seconds,
        culm_density=CULM_DENSITY,
        interpolate_forcings=INTERPOLATE_FORCINGS,
        senescence_forcings_delta_t=senescence_forcings_delta_t,
        photosynthesis_forcings_delta_t=photosynthesis_forcings_delta_t)

    # Initialize the simulation from the population of plants and the dictionary of soils created previously
    simulation_.initialize(population, soils)

    # get photosynthesis data
    photosynthesis_elements_data_filepath = os.path.join(
        INPUTS_DIRPATH, ELEMENTS_PHOTOSYNTHESIS_FORCINGS_FILENAME)
    photosynthesis_elements_data_df = pd.read_csv(
        photosynthesis_elements_data_filepath)
    photosynthesis_elements_data_grouped = photosynthesis_elements_data_df.groupby(
        cnwheat_simulation.Simulation.ELEMENTS_T_INDEXES)