예제 #1
0
def main(stop_time, run_simu=True, make_graphs=True):
    if run_simu:
        meteo = pd.read_csv(METEO_FILEPATH, index_col='t')
        Eabs_df = pd.read_csv(CARIBU_FILEPATH)

        # define the time step in hours for each simulator
        senescwheat_ts = 2
        growthwheat_ts = 2
        farquharwheat_ts = 2
        elongwheat_ts = 2
        cnwheat_ts = 1

        hour_to_second_conversion_factor = 3600

        # read adelwheat inputs at t0
        adel_wheat = AdelDyn(seed=1234, scene_unit='m')
        g = adel_wheat.load(dir=ADELWHEAT_INPUTS_DIRPATH)

        # adel_wheat.plot(g)

        # create empty dataframes to shared data between the models
        shared_axes_inputs_outputs_df = pd.DataFrame()
        shared_organs_inputs_outputs_df = pd.DataFrame()
        shared_hiddenzones_inputs_outputs_df = pd.DataFrame()
        shared_elements_inputs_outputs_df = pd.DataFrame()
        shared_soils_inputs_outputs_df = pd.DataFrame()

        # read the inputs at t0 and create the facades

        # caribu
        caribu_facade_ = caribu_facade.CaribuFacade(g,
                                                    shared_elements_inputs_outputs_df,
                                                    adel_wheat)

        # senescwheat
        senescwheat_roots_inputs_t0 = pd.read_csv(SENESCWHEAT_ROOTS_INPUTS_FILEPATH)
        senescwheat_axes_inputs_t0 = pd.read_csv(SENESCWHEAT_AXES_INPUTS_FILEPATH)
        senescwheat_elements_inputs_t0 = pd.read_csv(SENESCWHEAT_ELEMENTS_INPUTS_FILEPATH)
        senescwheat_facade_ = senescwheat_facade.SenescWheatFacade(g,
                                                                   senescwheat_ts * hour_to_second_conversion_factor,
                                                                   senescwheat_roots_inputs_t0,
                                                                   senescwheat_axes_inputs_t0,
                                                                   senescwheat_elements_inputs_t0,
                                                                   shared_organs_inputs_outputs_df,
                                                                   shared_axes_inputs_outputs_df,
                                                                   shared_elements_inputs_outputs_df)
        # growthwheat
        growthwheat_hiddenzones_inputs_t0 = pd.read_csv(GROWTHWHEAT_HIDDENZONE_INPUTS_FILEPATH)
        growthwheat_organ_inputs_t0 = pd.read_csv(GROWTHWHEAT_ORGANS_INPUTS_FILEPATH)
        growthwheat_root_inputs_t0 = pd.read_csv(GROWTHWHEAT_ROOTS_INPUTS_FILEPATH)
        growthwheat_axes_inputs_t0 = pd.read_csv(GROWTHWHEAT_AXES_INPUTS_FILEPATH)
        growthwheat_facade_ = growthwheat_facade.GrowthWheatFacade(g,
                                                                   growthwheat_ts * hour_to_second_conversion_factor,
                                                                   growthwheat_hiddenzones_inputs_t0,
                                                                   growthwheat_organ_inputs_t0,
                                                                   growthwheat_root_inputs_t0,
                                                                   growthwheat_axes_inputs_t0,
                                                                   shared_organs_inputs_outputs_df,
                                                                   shared_hiddenzones_inputs_outputs_df,
                                                                   shared_elements_inputs_outputs_df,
                                                                   shared_axes_inputs_outputs_df)

        # farquharwheat
        farquharwheat_elements_inputs_t0 = pd.read_csv(FARQUHARWHEAT_INPUTS_FILEPATH)
        farquharwheat_axes_inputs_t0 = pd.read_csv(FARQUHARWHEAT_AXES_INPUTS_FILEPATH)
        update_parameters_farquharwheat = {'MODEL_VERSION': 'Barillot2016'}  # Use the initial version of the photosynthesis sub-model (as in Barillot et al. 2016, and in Gauthier et al. 2020)

        farquharwheat_facade_ = farquharwheat_facade.FarquharWheatFacade(g,
                                                                         farquharwheat_elements_inputs_t0,
                                                                         farquharwheat_axes_inputs_t0,
                                                                         shared_elements_inputs_outputs_df,
                                                                         update_parameters=update_parameters_farquharwheat)

        # elongwheat # Only for temperature related computations
        elongwheat_hiddenzones_inputs_t0 = pd.read_csv(ELONGWHEAT_HZ_INPUTS_FILEPATH)
        elongwheat_elements_inputs_t0 = pd.read_csv(ELONGWHEAT_ELEMENTS_INPUTS_FILEPATH)
        elongwheat_axes_inputs_t0 = pd.read_csv(ELONGWHEAT_AXES_INPUTS_FILEPATH)

        elongwheat_facade_ = elongwheat_facade.ElongWheatFacade(g,
                                                                elongwheat_ts * hour_to_second_conversion_factor,
                                                                elongwheat_axes_inputs_t0,
                                                                elongwheat_hiddenzones_inputs_t0,
                                                                elongwheat_elements_inputs_t0,
                                                                shared_axes_inputs_outputs_df,
                                                                shared_hiddenzones_inputs_outputs_df,
                                                                shared_elements_inputs_outputs_df,
                                                                adel_wheat, option_static=True)
        # cnwheat
        cnwheat_organs_inputs_t0 = pd.read_csv(CNWHEAT_ORGANS_INPUTS_FILEPATH)
        cnwheat_hiddenzones_inputs_t0 = pd.read_csv(CNWHEAT_HIDDENZONE_INPUTS_FILEPATH)
        cnwheat_elements_inputs_t0 = pd.read_csv(CNWHEAT_ELEMENTS_INPUTS_FILEPATH)
        cnwheat_soils_inputs_t0 = pd.read_csv(CNWHEAT_SOILS_INPUTS_FILEPATH)
        update_cnwheat_parameters = {'roots': {'K_AMINO_ACIDS_EXPORT': 25*3E-5,
                                               'K_NITRATE_EXPORT': 25*1E-6}}

        cnwheat_facade_ = cnwheat_facade.CNWheatFacade(g,
                                                       cnwheat_ts * hour_to_second_conversion_factor,
                                                       CULM_DENSITY,
                                                       update_cnwheat_parameters,
                                                       cnwheat_organs_inputs_t0,
                                                       cnwheat_hiddenzones_inputs_t0,
                                                       cnwheat_elements_inputs_t0,
                                                       cnwheat_soils_inputs_t0,
                                                       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)

        # adel_wheat.update_geometry(g) # NE FONCTIONNE PAS car MTG non compatible (pas de top et base element)
        # adel_wheat.plot(g)

        # define organs for which the variable 'max_proteins' is fixed
        forced_max_protein_elements = {(1, 'MS', 9, 'blade', 'LeafElement1'), (1, 'MS', 10, 'blade', 'LeafElement1'), (1, 'MS', 11, 'blade', 'LeafElement1'), (2, 'MS', 9, 'blade', 'LeafElement1'),
                                       (2, 'MS', 10, 'blade', 'LeafElement1'), (2, 'MS', 11, 'blade', 'LeafElement1')}

        # define the start and the end of the whole simulation (in hours)
        start_time = 0
        stop_time = stop_time

        #  define lists of dataframes to store the inputs and the outputs of the models at each step.
        axes_all_data_list = []
        organs_all_data_list = []  # organs which belong to axes: roots, phloem, grains
        elements_all_data_list = []
        soils_all_data_list = []

        all_simulation_steps = []  # to store the steps of the simulation

        # run the simulators
        current_time_of_the_system = time.time()

        try:

            for t_elongwheat in range(start_time, stop_time, elongwheat_ts):  # Only to compute temperature related variable

                # run ElongWheat
                print('t elongwheat is {}'.format(t_elongwheat))
                Tair, Tsoil = meteo.loc[t_elongwheat, ['air_temperature', 'air_temperature']]
                elongwheat_facade_.run(Tair, Tsoil, option_static=True)

                for t_senescwheat in range(t_elongwheat, t_elongwheat + elongwheat_ts, senescwheat_ts):

                    # run SenescWheat
                    print('t senescwheat is {}'.format(t_senescwheat))
                    senescwheat_facade_.run(forced_max_protein_elements, postflowering_stages=True)

                    # Test for fully senesced shoot tissues  #TODO: Make the model to work even if the whole shoot is dead but the roots are alived
                    if sum(senescwheat_facade_._shared_elements_inputs_outputs_df['green_area']) <= 0.25E-6:
                        break

                    for t_growthwheat in range(t_senescwheat, t_senescwheat + senescwheat_ts, growthwheat_ts):
                        # run GrowthWheat
                        print('t growthwheat is {}'.format(t_growthwheat))
                        growthwheat_facade_.run(postflowering_stages=True)

                        for t_farquharwheat in range(t_growthwheat, t_growthwheat + growthwheat_ts, farquharwheat_ts):
                            # get the meteo of the current step
                            Tair, ambient_CO2, RH, Ur, PARi = meteo.loc[t_farquharwheat, ['air_temperature', 'ambient_CO2', 'humidity', 'Wind', 'PARi']]
                            # get PARa for current step
                            aggregated_PARa = calculate_PARa_from_df(g, Eabs_df, PARi, multiple_sources=False)
                            print('t caribu is {}'.format(t_farquharwheat))
                            # caribu_facade_.run(energy=PARi,sun_sky_option='sky')
                            caribu_facade_.update_shared_MTG({'PARa': aggregated_PARa})
                            caribu_facade_.update_shared_dataframes({'PARa': aggregated_PARa})
                            # run FarquharWheat
                            print('t farquhar is {}'.format(t_farquharwheat))
                            farquharwheat_facade_.run(Tair, ambient_CO2, RH, Ur)

                            for t_cnwheat in range(t_farquharwheat, t_farquharwheat + senescwheat_ts, cnwheat_ts):
                                Tair, Tsoil = meteo.loc[t_cnwheat, ['air_temperature', 'air_temperature']]
                                # run CNWheat
                                print('t cnwheat is {}'.format(t_cnwheat))
                                cnwheat_facade_.run(Tair=Tair, Tsoil=Tsoil)

                                # append the inputs and outputs at current step to global lists
                                all_simulation_steps.append(t_cnwheat)
                                axes_all_data_list.append(shared_axes_inputs_outputs_df.copy())
                                organs_all_data_list.append(shared_organs_inputs_outputs_df.copy())
                                elements_all_data_list.append(shared_elements_inputs_outputs_df.copy())
                                soils_all_data_list.append(shared_soils_inputs_outputs_df.copy())
                else:
                    continue
                break

        except Exception as ex:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type {0} occurred. Arguments:\n{1!r}"
            message = template.format(type(ex).__name__, ex.args)
            print(message, fname, exc_tb.tb_lineno)

        finally:
            execution_time = int(time.time() - current_time_of_the_system)
            print('\n', 'Simulation run in ', str(datetime.timedelta(seconds=execution_time)))

            # write all inputs and outputs to CSV files
            all_axes_inputs_outputs = pd.concat(axes_all_data_list, keys=all_simulation_steps)
            all_axes_inputs_outputs.reset_index(0, inplace=True)
            all_axes_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True)
            all_axes_inputs_outputs.to_csv(AXES_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

            all_organs_inputs_outputs = pd.concat(organs_all_data_list, keys=all_simulation_steps)
            all_organs_inputs_outputs.reset_index(0, inplace=True)
            all_organs_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True)
            all_organs_inputs_outputs.to_csv(ORGANS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

            all_elements_inputs_outputs = pd.concat(elements_all_data_list, keys=all_simulation_steps)
            all_elements_inputs_outputs.reset_index(0, inplace=True)
            all_elements_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True)
            all_elements_inputs_outputs.to_csv(ELEMENTS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

            all_soils_inputs_outputs = pd.concat(soils_all_data_list, keys=all_simulation_steps)
            all_soils_inputs_outputs.reset_index(0, inplace=True)
            all_soils_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True)
            all_soils_inputs_outputs.to_csv(SOILS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

    # -POST-PROCESSING##

    if make_graphs:
        generate_graphs()
예제 #2
0
def main(stop_time, run_simu=True, make_graphs=True):
    if run_simu:
        meteo = pd.read_csv(METEO_FILEPATH, index_col='t')
        Eabs_df = pd.read_csv(CARIBU_FILEPATH)

        # define the time step in hours for each simulator
        senescwheat_ts = 2
        growthwheat_ts = 2
        farquharwheat_ts = 2
        elongwheat_ts = 2
        cnwheat_ts = 1

        hour_to_second_conversion_factor = 3600

        # read adelwheat inputs at t0
        adel_wheat = AdelDyn(seed=1234, scene_unit='m')
        g = adel_wheat.load(dir=ADELWHEAT_INPUTS_DIRPATH)

        # adel_wheat.plot(g)

        # create empty dataframes to shared data between the models
        shared_axes_inputs_outputs_df = pd.DataFrame()
        shared_organs_inputs_outputs_df = pd.DataFrame()
        shared_hiddenzones_inputs_outputs_df = pd.DataFrame()
        shared_elements_inputs_outputs_df = pd.DataFrame()
        shared_soils_inputs_outputs_df = pd.DataFrame()

        # read the inputs at t0 and create the facades

        # caribu
        caribu_facade_ = caribu_facade.CaribuFacade(
            g, shared_elements_inputs_outputs_df, adel_wheat)

        # senescwheat
        senescwheat_roots_inputs_t0 = pd.read_csv(
            SENESCWHEAT_ROOTS_INPUTS_FILEPATH)
        senescwheat_axes_inputs_t0 = pd.read_csv(
            SENESCWHEAT_AXES_INPUTS_FILEPATH)
        senescwheat_elements_inputs_t0 = pd.read_csv(
            SENESCWHEAT_ELEMENTS_INPUTS_FILEPATH)
        senescwheat_facade_ = senescwheat_facade.SenescWheatFacade(
            g, senescwheat_ts * hour_to_second_conversion_factor,
            senescwheat_roots_inputs_t0, senescwheat_axes_inputs_t0,
            senescwheat_elements_inputs_t0, shared_organs_inputs_outputs_df,
            shared_axes_inputs_outputs_df, shared_elements_inputs_outputs_df)
        # growthwheat
        growthwheat_hiddenzones_inputs_t0 = pd.read_csv(
            GROWTHWHEAT_HIDDENZONE_INPUTS_FILEPATH)
        growthwheat_organ_inputs_t0 = pd.read_csv(
            GROWTHWHEAT_ORGANS_INPUTS_FILEPATH)
        growthwheat_root_inputs_t0 = pd.read_csv(
            GROWTHWHEAT_ROOTS_INPUTS_FILEPATH)
        growthwheat_axes_inputs_t0 = pd.read_csv(
            GROWTHWHEAT_AXES_INPUTS_FILEPATH)
        growthwheat_facade_ = growthwheat_facade.GrowthWheatFacade(
            g, growthwheat_ts * hour_to_second_conversion_factor,
            growthwheat_hiddenzones_inputs_t0, growthwheat_organ_inputs_t0,
            growthwheat_root_inputs_t0, growthwheat_axes_inputs_t0,
            shared_organs_inputs_outputs_df,
            shared_hiddenzones_inputs_outputs_df,
            shared_elements_inputs_outputs_df, shared_axes_inputs_outputs_df)

        # farquharwheat
        farquharwheat_elements_inputs_t0 = pd.read_csv(
            FARQUHARWHEAT_INPUTS_FILEPATH)
        farquharwheat_axes_inputs_t0 = pd.read_csv(
            FARQUHARWHEAT_AXES_INPUTS_FILEPATH)
        update_parameters_farquharwheat = {
            'MODEL_VERSION': 'Barillot2016'
        }  # Use the initial version of the photosynthesis sub-model (as in Barillot et al. 2016, and in Gauthier et al. 2020)

        farquharwheat_facade_ = farquharwheat_facade.FarquharWheatFacade(
            g,
            farquharwheat_elements_inputs_t0,
            farquharwheat_axes_inputs_t0,
            shared_elements_inputs_outputs_df,
            update_parameters=update_parameters_farquharwheat)

        # elongwheat # Only for temperature related computations
        elongwheat_hiddenzones_inputs_t0 = pd.read_csv(
            ELONGWHEAT_HZ_INPUTS_FILEPATH)
        elongwheat_elements_inputs_t0 = pd.read_csv(
            ELONGWHEAT_ELEMENTS_INPUTS_FILEPATH)
        elongwheat_axes_inputs_t0 = pd.read_csv(
            ELONGWHEAT_AXES_INPUTS_FILEPATH)

        elongwheat_facade_ = elongwheat_facade.ElongWheatFacade(
            g,
            elongwheat_ts * hour_to_second_conversion_factor,
            elongwheat_axes_inputs_t0,
            elongwheat_hiddenzones_inputs_t0,
            elongwheat_elements_inputs_t0,
            shared_axes_inputs_outputs_df,
            shared_hiddenzones_inputs_outputs_df,
            shared_elements_inputs_outputs_df,
            adel_wheat,
            option_static=True)
        # cnwheat
        cnwheat_organs_inputs_t0 = pd.read_csv(CNWHEAT_ORGANS_INPUTS_FILEPATH)
        cnwheat_hiddenzones_inputs_t0 = pd.read_csv(
            CNWHEAT_HIDDENZONE_INPUTS_FILEPATH)
        cnwheat_elements_inputs_t0 = pd.read_csv(
            CNWHEAT_ELEMENTS_INPUTS_FILEPATH)
        cnwheat_soils_inputs_t0 = pd.read_csv(CNWHEAT_SOILS_INPUTS_FILEPATH)
        update_cnwheat_parameters = {
            'roots': {
                'K_AMINO_ACIDS_EXPORT': 25 * 3E-5,
                'K_NITRATE_EXPORT': 25 * 1E-6
            }
        }

        cnwheat_facade_ = cnwheat_facade.CNWheatFacade(
            g, cnwheat_ts * hour_to_second_conversion_factor, CULM_DENSITY,
            update_cnwheat_parameters, cnwheat_organs_inputs_t0,
            cnwheat_hiddenzones_inputs_t0, cnwheat_elements_inputs_t0,
            cnwheat_soils_inputs_t0, 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)

        # adel_wheat.update_geometry(g) # NE FONCTIONNE PAS car MTG non compatible (pas de top et base element)
        # adel_wheat.plot(g)

        # define organs for which the variable 'max_proteins' is fixed
        forced_max_protein_elements = {(1, 'MS', 9, 'blade', 'LeafElement1'),
                                       (1, 'MS', 10, 'blade', 'LeafElement1'),
                                       (1, 'MS', 11, 'blade', 'LeafElement1'),
                                       (2, 'MS', 9, 'blade', 'LeafElement1'),
                                       (2, 'MS', 10, 'blade', 'LeafElement1'),
                                       (2, 'MS', 11, 'blade', 'LeafElement1')}

        # define the start and the end of the whole simulation (in hours)
        start_time = 0
        stop_time = stop_time

        #  define lists of dataframes to store the inputs and the outputs of the models at each step.
        axes_all_data_list = []
        organs_all_data_list = [
        ]  # organs which belong to axes: roots, phloem, grains
        elements_all_data_list = []
        soils_all_data_list = []

        all_simulation_steps = []  # to store the steps of the simulation

        # run the simulators
        current_time_of_the_system = time.time()

        for t_elongwheat in range(
                start_time, stop_time,
                elongwheat_ts):  # Only to compute temperature related variable

            # run ElongWheat
            print('t elongwheat is {}'.format(t_elongwheat))
            Tair, Tsoil = meteo.loc[t_elongwheat,
                                    ['air_temperature', 'air_temperature']]
            elongwheat_facade_.run(Tair, Tsoil, option_static=True)

            for t_senescwheat in range(t_elongwheat,
                                       t_elongwheat + elongwheat_ts,
                                       senescwheat_ts):

                # run SenescWheat
                print('t senescwheat is {}'.format(t_senescwheat))
                senescwheat_facade_.run(forced_max_protein_elements,
                                        postflowering_stages=True)

                # Test for fully senesced shoot tissues  #TODO: Make the model to work even if the whole shoot is dead but the roots are alived
                if sum(senescwheat_facade_._shared_elements_inputs_outputs_df[
                        'green_area']) <= 0.25E-6:
                    break

                for t_growthwheat in range(t_senescwheat,
                                           t_senescwheat + senescwheat_ts,
                                           growthwheat_ts):
                    # run GrowthWheat
                    print('t growthwheat is {}'.format(t_growthwheat))
                    growthwheat_facade_.run(postflowering_stages=True)

                    for t_farquharwheat in range(
                            t_growthwheat, t_growthwheat + growthwheat_ts,
                            farquharwheat_ts):
                        # get the meteo of the current step
                        Tair, ambient_CO2, RH, Ur, PARi = meteo.loc[
                            t_farquharwheat, [
                                'air_temperature', 'ambient_CO2', 'humidity',
                                'Wind', 'PARi'
                            ]]
                        # get PARa for current step
                        aggregated_PARa = calculate_PARa_from_df(
                            g, Eabs_df, PARi, multiple_sources=False)
                        print('t caribu is {}'.format(t_farquharwheat))
                        # caribu_facade_.run(energy=PARi,sun_sky_option='sky')
                        caribu_facade_.update_shared_MTG(
                            {'PARa': aggregated_PARa})
                        caribu_facade_.update_shared_dataframes(
                            {'PARa': aggregated_PARa})
                        # run FarquharWheat
                        print('t farquhar is {}'.format(t_farquharwheat))
                        farquharwheat_facade_.run(Tair, ambient_CO2, RH, Ur)

                        for t_cnwheat in range(
                                t_farquharwheat,
                                t_farquharwheat + senescwheat_ts, cnwheat_ts):
                            Tair, Tsoil = meteo.loc[
                                t_cnwheat,
                                ['air_temperature', 'air_temperature']]
                            # run CNWheat
                            print('t cnwheat is {}'.format(t_cnwheat))
                            cnwheat_facade_.run(Tair=Tair, Tsoil=Tsoil)

                            # append the inputs and outputs at current step to global lists
                            all_simulation_steps.append(t_cnwheat)
                            axes_all_data_list.append(
                                shared_axes_inputs_outputs_df.copy())
                            organs_all_data_list.append(
                                shared_organs_inputs_outputs_df.copy())
                            elements_all_data_list.append(
                                shared_elements_inputs_outputs_df.copy())
                            soils_all_data_list.append(
                                shared_soils_inputs_outputs_df.copy())
            else:
                continue
            break

        execution_time = int(time.time() - current_time_of_the_system)
        print('\n', 'Simulation run in ',
              str(datetime.timedelta(seconds=execution_time)))

        # write all inputs and outputs to CSV files
        all_axes_inputs_outputs = pd.concat(axes_all_data_list,
                                            keys=all_simulation_steps)
        all_axes_inputs_outputs.reset_index(0, inplace=True)
        all_axes_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True)
        all_axes_inputs_outputs.to_csv(
            AXES_STATES_FILEPATH,
            na_rep='NA',
            index=False,
            float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

        all_organs_inputs_outputs = pd.concat(organs_all_data_list,
                                              keys=all_simulation_steps)
        all_organs_inputs_outputs.reset_index(0, inplace=True)
        all_organs_inputs_outputs.rename({'level_0': 't'},
                                         axis=1,
                                         inplace=True)
        all_organs_inputs_outputs.to_csv(
            ORGANS_STATES_FILEPATH,
            na_rep='NA',
            index=False,
            float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

        all_elements_inputs_outputs = pd.concat(elements_all_data_list,
                                                keys=all_simulation_steps)
        all_elements_inputs_outputs.reset_index(0, inplace=True)
        all_elements_inputs_outputs.rename({'level_0': 't'},
                                           axis=1,
                                           inplace=True)
        all_elements_inputs_outputs.to_csv(
            ELEMENTS_STATES_FILEPATH,
            na_rep='NA',
            index=False,
            float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

        all_soils_inputs_outputs = pd.concat(soils_all_data_list,
                                             keys=all_simulation_steps)
        all_soils_inputs_outputs.reset_index(0, inplace=True)
        all_soils_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True)
        all_soils_inputs_outputs.to_csv(
            SOILS_STATES_FILEPATH,
            na_rep='NA',
            index=False,
            float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION))

    # -POST-PROCESSING##

    if make_graphs:

        # POST PROCESSINGS

        states_df_dict = {}
        for states_filepath in (AXES_STATES_FILEPATH, ORGANS_STATES_FILEPATH,
                                ELEMENTS_STATES_FILEPATH,
                                SOILS_STATES_FILEPATH):
            # assert states_filepaths were not opened during simulation run meaning that other filenames were saved
            path, filename = os.path.split(states_filepath)
            filename = os.path.splitext(filename)[0]
            newfilename = 'ACTUAL_{}.csv'.format(filename)
            newpath = os.path.join(path, newfilename)
            assert not os.path.isfile(newpath), \
                "File {} was saved because {} was opened during simulation run. Rename it before running postprocessing".format(newfilename, states_filepath)

            # Retrieve outputs dataframes from precedent simulation run
            states_df = pd.read_csv(states_filepath)
            states_file_basename = os.path.basename(states_filepath).split(
                '.')[0]
            states_df_dict[states_file_basename] = states_df
        time_grid = states_df_dict['elements_states']['t']
        delta_t = (time_grid.unique()[1] -
                   time_grid.unique()[0]) * HOUR_TO_SECOND_CONVERSION_FACTOR

        # run the postprocessing
        axes_postprocessing_file_basename = os.path.basename(
            AXES_POSTPROCESSING_FILEPATH).split('.')[0]
        organs_postprocessing_file_basename = os.path.basename(
            ORGANS_POSTPROCESSING_FILEPATH).split('.')[0]
        elements_postprocessing_file_basename = os.path.basename(
            ELEMENTS_POSTPROCESSING_FILEPATH).split('.')[0]
        soils_postprocessing_file_basename = os.path.basename(
            SOILS_POSTPROCESSING_FILEPATH).split('.')[0]
        postprocessing_df_dict = {}
        (postprocessing_df_dict[axes_postprocessing_file_basename],
         _,
         postprocessing_df_dict[organs_postprocessing_file_basename],
         postprocessing_df_dict[elements_postprocessing_file_basename],
         postprocessing_df_dict[soils_postprocessing_file_basename]) \
            = cnwheat_facade.CNWheatFacade.postprocessing(axes_outputs_df=states_df_dict[os.path.basename(AXES_STATES_FILEPATH).split('.')[0]],
                                                          organs_outputs_df=states_df_dict[os.path.basename(ORGANS_STATES_FILEPATH).split('.')[0]],
                                                          hiddenzone_outputs_df=None,
                                                          elements_outputs_df=states_df_dict[os.path.basename(ELEMENTS_STATES_FILEPATH).split('.')[0]],
                                                          soils_outputs_df=states_df_dict[os.path.basename(SOILS_STATES_FILEPATH).split('.')[0]],
                                                          delta_t=delta_t)

        # save the postprocessing to disk
        for postprocessing_file_basename, postprocessing_filepath in (
            (axes_postprocessing_file_basename, AXES_POSTPROCESSING_FILEPATH),
            (organs_postprocessing_file_basename,
             ORGANS_POSTPROCESSING_FILEPATH),
            (elements_postprocessing_file_basename,
             ELEMENTS_POSTPROCESSING_FILEPATH),
            (soils_postprocessing_file_basename,
             SOILS_POSTPROCESSING_FILEPATH)):
            postprocessing_df_dict[postprocessing_file_basename].to_csv(
                postprocessing_filepath,
                na_rep='NA',
                index=False,
                float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION + 5))

        # - GRAPHS

        # Retrieve last computed post-processing dataframes
        axes_postprocessing_file_basename = os.path.basename(
            AXES_POSTPROCESSING_FILEPATH).split('.')[0]
        organs_postprocessing_file_basename = os.path.basename(
            ORGANS_POSTPROCESSING_FILEPATH).split('.')[0]
        elements_postprocessing_file_basename = os.path.basename(
            ELEMENTS_POSTPROCESSING_FILEPATH).split('.')[0]
        soils_postprocessing_file_basename = os.path.basename(
            SOILS_POSTPROCESSING_FILEPATH).split('.')[0]
        postprocessing_df_dict = {}
        for (postprocessing_filepath, postprocessing_file_basename) in (
            (AXES_POSTPROCESSING_FILEPATH, axes_postprocessing_file_basename),
            (ORGANS_POSTPROCESSING_FILEPATH,
             organs_postprocessing_file_basename),
            (ELEMENTS_POSTPROCESSING_FILEPATH,
             elements_postprocessing_file_basename),
            (SOILS_POSTPROCESSING_FILEPATH,
             soils_postprocessing_file_basename)):
            postprocessing_df = pd.read_csv(postprocessing_filepath)
            postprocessing_df_dict[
                postprocessing_file_basename] = postprocessing_df

        # Generate graphs
        cnwheat_facade.CNWheatFacade.graphs(
            axes_postprocessing_df=postprocessing_df_dict[
                axes_postprocessing_file_basename],
            hiddenzones_postprocessing_df=None,
            organs_postprocessing_df=postprocessing_df_dict[
                organs_postprocessing_file_basename],
            elements_postprocessing_df=postprocessing_df_dict[
                elements_postprocessing_file_basename],
            soils_postprocessing_df=postprocessing_df_dict[
                soils_postprocessing_file_basename],
            graphs_dirpath=GRAPHS_DIRPATH)
예제 #3
0
def test_run(overwrite_desired_data=False):
    # ---------------------------------------------
    # ----- CONFIGURATION OF THE SIMULATION -------
    # ---------------------------------------------

    # -- INPUTS CONFIGURATION --

    # Path of the directory which contains the inputs of the model
    INPUTS_DIRPATH = 'inputs'

    # Name of the CSV files which describes the initial state of the system
    AXES_INITIAL_STATE_FILENAME = 'axes_initial_state.csv'
    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'
    METEO_FILENAME = 'meteo_Ljutovac2002.csv'

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

    # -- SIMULATION PARAMETERS --
    START_TIME = 0
    SIMULATION_LENGTH = 24
    PLANT_DENSITY = {1: 410}

    # define the time step in hours for each simulator
    CARIBU_TIMESTEP = 4
    SENESCWHEAT_TIMESTEP = 2
    FARQUHARWHEAT_TIMESTEP = 2
    ELONGWHEAT_TIMESTEP = 1
    GROWTHWHEAT_TIMESTEP = 1
    CNWHEAT_TIMESTEP = 1

    # Name of the CSV files which contains the meteo data
    meteo = pd.read_csv(os.path.join(INPUTS_DIRPATH, METEO_FILENAME),
                        index_col='t')

    # -- OUTPUTS CONFIGURATION --
    # Path of the directory which contains the inputs of the model
    OUTPUTS_DIRPATH = 'outputs'

    # Name of the CSV files which will contain the outputs of the model
    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'

    # create empty dataframes to shared data between the models
    shared_axes_inputs_outputs_df = pd.DataFrame()
    shared_organs_inputs_outputs_df = pd.DataFrame()
    shared_hiddenzones_inputs_outputs_df = pd.DataFrame()
    shared_elements_inputs_outputs_df = pd.DataFrame()
    shared_soils_inputs_outputs_df = pd.DataFrame()

    # define lists of dataframes to store the inputs and the outputs of the models at each step.
    axes_all_data_list = []
    organs_all_data_list = [
    ]  # organs which belong to axes: roots, phloem, grains
    hiddenzones_all_data_list = []
    elements_all_data_list = []
    soils_all_data_list = []

    all_simulation_steps = []  # to store the steps of the simulation

    # -- ADEL and MTG CONFIGURATION --

    # read adelwheat inputs at t0
    adel_wheat = AdelDyn(seed=1,
                         scene_unit='m',
                         leaves=echap_leaves(xy_model='Soissons_byleafclass'))
    g = adel_wheat.load(dir=INPUTS_DIRPATH)

    # ---------------------------------------------
    # ----- CONFIGURATION OF THE FACADES -------
    # ---------------------------------------------

    # -- ELONGWHEAT (created first because it is the only facade to add new metamers) --
    # Initial states
    elongwheat_hiddenzones_initial_state = inputs_dataframes[
        HIDDENZONES_INITIAL_STATE_FILENAME][
            elongwheat_facade.converter.HIDDENZONE_TOPOLOGY_COLUMNS + [
                i
                for i in elongwheat_facade.simulation.HIDDENZONE_INPUTS if i in
                inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME].columns
            ]].copy()
    elongwheat_elements_initial_state = inputs_dataframes[
        ELEMENTS_INITIAL_STATE_FILENAME][
            elongwheat_facade.converter.ELEMENT_TOPOLOGY_COLUMNS + [
                i for i in elongwheat_facade.simulation.ELEMENT_INPUTS if i in
                inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns
            ]].copy()
    elongwheat_axes_initial_state = inputs_dataframes[
        AXES_INITIAL_STATE_FILENAME][
            elongwheat_facade.converter.AXIS_TOPOLOGY_COLUMNS + [
                i for i in elongwheat_facade.simulation.AXIS_INPUTS
                if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns
            ]].copy()

    phytoT = os.path.join(INPUTS_DIRPATH, 'phytoT.csv')

    # Update some parameters
    update_cnwheat_parameters = {'SL_ratio_d': 0.25}

    # Facade initialisation
    elongwheat_facade_ = elongwheat_facade.ElongWheatFacade(
        g, ELONGWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR,
        elongwheat_axes_initial_state, elongwheat_hiddenzones_initial_state,
        elongwheat_elements_initial_state, shared_axes_inputs_outputs_df,
        shared_hiddenzones_inputs_outputs_df,
        shared_elements_inputs_outputs_df, adel_wheat, phytoT,
        update_cnwheat_parameters)

    # -- CARIBU --
    caribu_facade_ = caribu_facade.CaribuFacade(
        g, shared_elements_inputs_outputs_df, adel_wheat)

    # -- SENESCWHEAT --
    # Initial states
    senescwheat_roots_initial_state = inputs_dataframes[
        ORGANS_INITIAL_STATE_FILENAME].loc[
            inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME]['organ'] ==
            'roots'][senescwheat_facade.converter.ROOTS_TOPOLOGY_COLUMNS + [
                i
                for i in senescwheat_facade.converter.SENESCWHEAT_ROOTS_INPUTS
                if i in
                inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME].columns
            ]].copy()

    senescwheat_elements_initial_state = inputs_dataframes[
        ELEMENTS_INITIAL_STATE_FILENAME][
            senescwheat_facade.converter.ELEMENTS_TOPOLOGY_COLUMNS + [
                i for i in
                senescwheat_facade.converter.SENESCWHEAT_ELEMENTS_INPUTS if i
                in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns
            ]].copy()

    senescwheat_axes_initial_state = inputs_dataframes[
        AXES_INITIAL_STATE_FILENAME][
            senescwheat_facade.converter.AXES_TOPOLOGY_COLUMNS + [
                i for i in senescwheat_facade.converter.SENESCWHEAT_AXES_INPUTS
                if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns
            ]].copy()

    # Update some parameters
    update_cnwheat_parameters = {'AGE_EFFECT_SENESCENCE': 10000}

    # Facade initialisation
    senescwheat_facade_ = senescwheat_facade.SenescWheatFacade(
        g, SENESCWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR,
        senescwheat_roots_initial_state, senescwheat_axes_initial_state,
        senescwheat_elements_initial_state, shared_organs_inputs_outputs_df,
        shared_axes_inputs_outputs_df, shared_elements_inputs_outputs_df,
        update_cnwheat_parameters)

    # -- FARQUHARWHEAT --
    # Initial states
    farquharwheat_elements_initial_state = inputs_dataframes[
        ELEMENTS_INITIAL_STATE_FILENAME][
            farquharwheat_facade.converter.ELEMENT_TOPOLOGY_COLUMNS + [
                i for i in
                farquharwheat_facade.converter.FARQUHARWHEAT_ELEMENTS_INPUTS if
                i in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns
            ]].copy()

    farquharwheat_axes_initial_state = inputs_dataframes[
        AXES_INITIAL_STATE_FILENAME][
            farquharwheat_facade.converter.AXIS_TOPOLOGY_COLUMNS + [
                i for i in
                farquharwheat_facade.converter.FARQUHARWHEAT_AXES_INPUTS
                if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns
            ]].copy()

    # Facade initialisation
    farquharwheat_facade_ = farquharwheat_facade.FarquharWheatFacade(
        g, farquharwheat_elements_initial_state,
        farquharwheat_axes_initial_state, shared_elements_inputs_outputs_df)

    # -- GROWTHWHEAT --
    # Initial states
    growthwheat_hiddenzones_initial_state = inputs_dataframes[
        HIDDENZONES_INITIAL_STATE_FILENAME][
            growthwheat_facade.converter.HIDDENZONE_TOPOLOGY_COLUMNS + [
                i for i in growthwheat_facade.simulation.HIDDENZONE_INPUTS
                if i in
                inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME].columns
            ]].copy()

    growthwheat_elements_initial_state = inputs_dataframes[
        ELEMENTS_INITIAL_STATE_FILENAME][
            growthwheat_facade.converter.ELEMENT_TOPOLOGY_COLUMNS + [
                i for i in growthwheat_facade.simulation.ELEMENT_INPUTS if i in
                inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns
            ]].copy()

    growthwheat_root_initial_state = inputs_dataframes[
        ORGANS_INITIAL_STATE_FILENAME].loc[
            inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME]['organ'] ==
            'roots'][growthwheat_facade.converter.ROOT_TOPOLOGY_COLUMNS + [
                i for i in growthwheat_facade.simulation.ROOT_INPUTS if i in
                inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME].columns
            ]].copy()

    growthwheat_axes_initial_state = inputs_dataframes[
        AXES_INITIAL_STATE_FILENAME][
            growthwheat_facade.converter.AXIS_TOPOLOGY_COLUMNS + [
                i for i in growthwheat_facade.simulation.AXIS_INPUTS
                if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns
            ]].copy()

    # Update some parameters
    update_cnwheat_parameters = {'VMAX_ROOTS_GROWTH_PREFLO': 0.02885625}

    # Facade initialisation
    growthwheat_facade_ = growthwheat_facade.GrowthWheatFacade(
        g, GROWTHWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR,
        growthwheat_hiddenzones_initial_state,
        growthwheat_elements_initial_state, growthwheat_root_initial_state,
        growthwheat_axes_initial_state, shared_organs_inputs_outputs_df,
        shared_hiddenzones_inputs_outputs_df,
        shared_elements_inputs_outputs_df, shared_axes_inputs_outputs_df,
        update_cnwheat_parameters)

    # -- CNWHEAT --
    # Initial states
    cnwheat_organs_initial_state = inputs_dataframes[
        ORGANS_INITIAL_STATE_FILENAME][[
            i for i in cnwheat_facade.cnwheat_converter.ORGANS_VARIABLES
            if i in inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME].columns
        ]].copy()

    cnwheat_hiddenzones_initial_state = inputs_dataframes[
        HIDDENZONES_INITIAL_STATE_FILENAME][[
            i for i in cnwheat_facade.cnwheat_converter.HIDDENZONE_VARIABLES if
            i in inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME].columns
        ]].copy()

    cnwheat_elements_initial_state = inputs_dataframes[
        ELEMENTS_INITIAL_STATE_FILENAME][[
            i for i in cnwheat_facade.cnwheat_converter.ELEMENTS_VARIABLES
            if i in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns
        ]].copy()

    cnwheat_soils_initial_state = inputs_dataframes[
        SOILS_INITIAL_STATE_FILENAME][[
            i for i in cnwheat_facade.cnwheat_converter.SOILS_VARIABLES
            if i in inputs_dataframes[SOILS_INITIAL_STATE_FILENAME].columns
        ]].copy()

    # Update some parameters
    update_cnwheat_parameters = {
        'roots': {
            'K_AMINO_ACIDS_EXPORT': 3E-5,
            'K_NITRATE_EXPORT': 1E-6
        }
    }

    # Facade initialisation
    cnwheat_facade_ = cnwheat_facade.CNWheatFacade(
        g, CNWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR, PLANT_DENSITY,
        cnwheat_organs_initial_state, cnwheat_hiddenzones_initial_state,
        cnwheat_elements_initial_state, cnwheat_soils_initial_state,
        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_cnwheat_parameters)

    # ---------------------------------------------
    # -----      RUN OF THE SIMULATION      -------
    # ---------------------------------------------

    for t_caribu in range(START_TIME, SIMULATION_LENGTH, CARIBU_TIMESTEP):
        # run Caribu
        PARi = meteo.loc[t_caribu, ['PARi_MA4']].iloc[0]
        DOY = meteo.loc[t_caribu, ['DOY']].iloc[0]
        hour = meteo.loc[t_caribu, ['hour']].iloc[0]
        caribu_facade_.run(energy=PARi,
                           DOY=DOY,
                           hourTU=hour,
                           latitude=48.85,
                           sun_sky_option='sky',
                           heterogeneous_canopy=True,
                           plant_density=PLANT_DENSITY[1])

        for t_senescwheat in range(t_caribu, t_caribu + CARIBU_TIMESTEP,
                                   SENESCWHEAT_TIMESTEP):
            # run SenescWheat
            senescwheat_facade_.run()

            # Run the rest of the model if the plant is alive
            for t_farquharwheat in range(t_senescwheat,
                                         t_senescwheat + SENESCWHEAT_TIMESTEP,
                                         FARQUHARWHEAT_TIMESTEP):
                # get the meteo of the current step
                Ta, ambient_CO2, RH, Ur = meteo.loc[t_farquharwheat, [
                    'air_temperature_MA2', 'ambient_CO2_MA2', 'humidity_MA2',
                    'Wind_MA2'
                ]]

                # run FarquharWheat
                farquharwheat_facade_.run(Ta, ambient_CO2, RH, Ur)

                for t_elongwheat in range(
                        t_farquharwheat,
                        t_farquharwheat + FARQUHARWHEAT_TIMESTEP,
                        ELONGWHEAT_TIMESTEP):
                    # run ElongWheat
                    Tair, Tsoil = meteo.loc[
                        t_elongwheat, ['air_temperature', 'soil_temperature']]
                    elongwheat_facade_.run(Tair, Tsoil, option_static=False)

                    # Update geometry
                    adel_wheat.update_geometry(g)

                    for t_growthwheat in range(
                            t_elongwheat, t_elongwheat + ELONGWHEAT_TIMESTEP,
                            GROWTHWHEAT_TIMESTEP):
                        # run GrowthWheat
                        growthwheat_facade_.run()

                        for t_cnwheat in range(
                                t_growthwheat,
                                t_growthwheat + GROWTHWHEAT_TIMESTEP,
                                CNWHEAT_TIMESTEP):
                            if t_cnwheat > 0:

                                # run CNWheat
                                Tair = meteo.loc[t_elongwheat,
                                                 'air_temperature']
                                Tsoil = meteo.loc[t_elongwheat,
                                                  'soil_temperature']
                                cnwheat_facade_.run(Tair, Tsoil)

                            # append outputs at current step to global lists
                            all_simulation_steps.append(t_cnwheat)
                            axes_all_data_list.append(
                                shared_axes_inputs_outputs_df.copy())
                            organs_all_data_list.append(
                                shared_organs_inputs_outputs_df.copy())
                            hiddenzones_all_data_list.append(
                                shared_hiddenzones_inputs_outputs_df.copy())
                            elements_all_data_list.append(
                                shared_elements_inputs_outputs_df.copy())
                            soils_all_data_list.append(
                                shared_soils_inputs_outputs_df.copy())

    # 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_all_data_list, DESIRED_AXES_OUTPUTS_FILENAME, ACTUAL_AXES_OUTPUTS_FILENAME, AXES_INDEX_COLUMNS),
                (organs_all_data_list, DESIRED_ORGANS_OUTPUTS_FILENAME, ACTUAL_ORGANS_OUTPUTS_FILENAME, ORGANS_INDEX_COLUMNS),
                (hiddenzones_all_data_list, DESIRED_HIDDENZONES_OUTPUTS_FILENAME, ACTUAL_HIDDENZONES_OUTPUTS_FILENAME, HIDDENZONES_INDEX_COLUMNS),
                (elements_all_data_list, DESIRED_ELEMENTS_OUTPUTS_FILENAME, ACTUAL_ELEMENTS_OUTPUTS_FILENAME, ELEMENTS_INDEX_COLUMNS),
                (soils_all_data_list, DESIRED_SOILS_OUTPUTS_FILENAME, ACTUAL_SOILS_OUTPUTS_FILENAME, SOILS_INDEX_COLUMNS)):
        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)