def run(self, Tair=12, Tsoil=12, tillers_replications=None, update_shared_df=None): """ Run the model and update the MTG and the dataframes shared between all models. :param update_shared_df: :param float Tair: air temperature (°C) :param float Tsoil: soil temperature (°C) :param dict [str, float] tillers_replications: a dictionary with tiller id as key, and weight of replication as value. :param bool update_shared_df: if 'True', update the shared dataframes at this time step. """ self._initialize_model(Tair=Tair, Tsoil=Tsoil, tillers_replications=tillers_replications) self._simulation.run() self._update_shared_MTG() if update_shared_df or (update_shared_df is None and self._update_shared_df): _, cnwheat_axes_inputs_outputs_df, _, cnwheat_organs_inputs_outputs_df, cnwheat_hiddenzones_inputs_outputs_df, cnwheat_elements_inputs_outputs_df, cnwheat_soils_inputs_outputs_df = \ cnwheat_converter.to_dataframes(self._simulation.population, self._simulation.soils) self._update_shared_dataframes( cnwheat_axes_data_df=cnwheat_axes_inputs_outputs_df, cnwheat_organs_data_df=cnwheat_organs_inputs_outputs_df, cnwheat_hiddenzones_data_df= cnwheat_hiddenzones_inputs_outputs_df, cnwheat_elements_data_df=cnwheat_elements_inputs_outputs_df, cnwheat_soils_data_df=cnwheat_soils_inputs_outputs_df)
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)
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)
soils_outputs_df_list = [] print('Prepare the simulation... DONE!') print('Run the simulation...') current_time_of_the_system = datetime.datetime.now() for t in time_grid: if t > 0: # Run the model of CN exchanges ; the population is internally updated by the model print('\tt =', t) simulation_.run() # Convert 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,