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_INDEX_COLUMNS = ['t', 'plant', 'axis'] # Define culm density (culm m-2) DENSITY = 410. NPLANTS = 1 CULM_DENSITY = {i: DENSITY / NPLANTS for i in range(1, NPLANTS + 1)} INPUTS_OUTPUTS_PRECISION = 5 # 10 LOGGING_CONFIG_FILEPATH = os.path.join('logging.json') LOGGING_LEVEL = logging.INFO # can be one of: DEBUG, INFO, WARNING, ERROR, CRITICAL cnwheat_tools.setup_logging(LOGGING_CONFIG_FILEPATH, LOGGING_LEVEL, log_model=False, log_compartments=False, log_derivatives=False) def calculate_PARa_from_df(g, Eabs_df, PARi, multiple_sources=False, ratio_diffus_PAR=None): """ Compute PARa from an input dataframe having Eabs values. """ Eabs_df_grouped = Eabs_df.groupby(['plant', 'metamer', 'organ'])
ELEMENTS_STATE)].dropna().to_dict() element.__dict__.update( photosynthesis_elements_data_to_use) if RUN_SIMU: print('Prepare the simulation...') time_step_seconds = TIME_STEP * HOUR_TO_SECOND_CONVERSION_FACTOR if LOG_EXECUTION: # Setup the logging cnwheat_tools.setup_logging(config_filepath=LOGGING_CONFIG_FILEPATH, level=logging.DEBUG, log_model=True, log_compartments=True, log_derivatives=True, remove_old_logs=True) # 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],