diff --git a/docs/Users_Guide/glossary.rst b/docs/Users_Guide/glossary.rst index b973d300d4..a7076d6206 100644 --- a/docs/Users_Guide/glossary.rst +++ b/docs/Users_Guide/glossary.rst @@ -7162,3 +7162,12 @@ METplus Configuration Glossary variable OR :term:`EXTRACT_TILES_TC_STAT_INPUT_TEMPLATE` but not both. | *Used by:* ExtractTiles + + TC_PAIRS_SKIP_LEAD_SEQ + If True and a forecast lead sequence is set in the configuration, do not + loop over list of leads and process for each. This is used for feature + relative use cases where TCPairs is run for each storm initialization time + and SeriesAnalysis is configured to filter the data by forecast leads. + Default value is False. + + | *Used by:* TCPairs diff --git a/docs/Users_Guide/wrappers.rst b/docs/Users_Guide/wrappers.rst index 98c8a47144..341a71405c 100644 --- a/docs/Users_Guide/wrappers.rst +++ b/docs/Users_Guide/wrappers.rst @@ -5393,6 +5393,7 @@ METplus Configuration | :term:`TC_PAIRS_CONSENSUS_MEMBERS` | :term:`TC_PAIRS_CONSENSUS_REQUIRED` | :term:`TC_PAIRS_CONSENSUS_MIN_REQ` +| :term:`TC_PAIRS_SKIP_LEAD_SEQ` | .. warning:: **DEPRECATED:** diff --git a/internal_tests/pytests/tc_pairs/test_tc_pairs_wrapper.py b/internal_tests/pytests/tc_pairs/test_tc_pairs_wrapper.py index 1db9b8e652..e662b1ee17 100644 --- a/internal_tests/pytests/tc_pairs/test_tc_pairs_wrapper.py +++ b/internal_tests/pytests/tc_pairs/test_tc_pairs_wrapper.py @@ -15,7 +15,7 @@ time_fmt = '%Y%m%d%H' run_times = ['2014121318'] -def set_minimum_config_settings(config): +def set_minimum_config_settings(config, loop_by='INIT'): # set config variables to prevent command from running and bypass check # if input files actually exist config.set('config', 'DO_NOT_RUN_EXE', True) @@ -23,11 +23,11 @@ def set_minimum_config_settings(config): # set process and time config variables config.set('config', 'PROCESS_LIST', 'TCPairs') - config.set('config', 'LOOP_BY', 'INIT') - config.set('config', 'INIT_TIME_FMT', time_fmt) - config.set('config', 'INIT_BEG', run_times[0]) - config.set('config', 'INIT_END', run_times[-1]) - config.set('config', 'INIT_INCREMENT', '12H') + config.set('config', 'LOOP_BY', loop_by) + config.set('config', f'{loop_by}_TIME_FMT', time_fmt) + config.set('config', f'{loop_by}_BEG', run_times[0]) + config.set('config', f'{loop_by}_END', run_times[-1]) + config.set('config', f'{loop_by}_INCREMENT', '12H') config.set('config', 'TC_PAIRS_CONFIG_FILE', '{PARM_BASE}/met_config/TCPairsConfig_wrapped') config.set('config', 'TC_PAIRS_BDECK_TEMPLATE', bdeck_template) @@ -264,7 +264,7 @@ def test_tc_pairs_storm_id_lists(metplus_config, config_overrides, config.set('config', key, value) wrapper = TCPairsWrapper(config) - assert(wrapper.isOK) + assert wrapper.isOK all_cmds = wrapper.run_all_times() print(f"ALL COMMANDS:") @@ -356,65 +356,78 @@ def test_tc_pairs_storm_id_lists(metplus_config, config_overrides, ) def test_tc_pairs_loop_order_processes(metplus_config, config_overrides, env_var_values): - - config = metplus_config() - - set_minimum_config_settings(config) - - test_data_dir = os.path.join(config.getdir('METPLUS_BASE'), - 'internal_tests', - 'data', - 'tc_pairs') - bdeck_dir = os.path.join(test_data_dir, 'bdeck') - adeck_dir = os.path.join(test_data_dir, 'adeck') - - config.set('config', 'TC_PAIRS_BDECK_INPUT_DIR', bdeck_dir) - config.set('config', 'TC_PAIRS_ADECK_INPUT_DIR', adeck_dir) - - # LOOP_ORDER processes runs once, times runs once per time - config.set('config', 'LOOP_ORDER', 'processes') - - # set config variable overrides - for key, value in config_overrides.items(): - config.set('config', key, value) - - if 'METPLUS_INIT_BEG' not in env_var_values: - env_var_values['METPLUS_INIT_BEG'] = f'init_beg = "{run_times[0]}";' - - if 'METPLUS_INIT_END' not in env_var_values: - env_var_values['METPLUS_INIT_END'] = f'init_end = "{run_times[-1]}";' - - wrapper = TCPairsWrapper(config) - assert(wrapper.isOK) - - app_path = os.path.join(config.getdir('MET_BIN_DIR'), wrapper.app_name) - verbosity = f"-v {wrapper.c_dict['VERBOSITY']}" - config_file = wrapper.c_dict.get('CONFIG_FILE') - out_dir = wrapper.c_dict.get('OUTPUT_DIR') - expected_cmds = [(f"{app_path} {verbosity} " - f"-bdeck {bdeck_dir}/bmlq2014123118.gfso.0104 " - f"-adeck {adeck_dir}/amlq2014123118.gfso.0104 " - f"-config {config_file} " - f"-out {out_dir}/mlq2014121318.gfso.0104"), - ] - - - all_cmds = wrapper.run_all_times() - print(f"ALL COMMANDS: {all_cmds}") - assert(len(all_cmds) == len(expected_cmds)) - - for (cmd, env_vars), expected_cmd in zip(all_cmds, expected_cmds): - # ensure commands are generated as expected - assert(cmd == expected_cmd) - - # check that environment variables were set properly - for env_var_key in wrapper.WRAPPER_ENV_VAR_KEYS: - match = next((item for item in env_vars if - item.startswith(env_var_key)), None) - assert(match is not None) - print(f'Checking env var: {env_var_key}') - actual_value = match.split('=', 1)[1] - assert(env_var_values.get(env_var_key, '') == actual_value) + # run using init and valid time variables + for loop_by in ['INIT', 'VALID']: + remove_beg = remove_end = False + config = metplus_config() + + set_minimum_config_settings(config, loop_by) + + test_data_dir = os.path.join(config.getdir('METPLUS_BASE'), + 'internal_tests', + 'data', + 'tc_pairs') + bdeck_dir = os.path.join(test_data_dir, 'bdeck') + adeck_dir = os.path.join(test_data_dir, 'adeck') + + config.set('config', 'TC_PAIRS_BDECK_INPUT_DIR', bdeck_dir) + config.set('config', 'TC_PAIRS_ADECK_INPUT_DIR', adeck_dir) + + # LOOP_ORDER processes runs once, times runs once per time + config.set('config', 'LOOP_ORDER', 'processes') + + # set config variable overrides + for key, value in config_overrides.items(): + config.set('config', key, value) + + if f'METPLUS_{loop_by}_BEG' not in env_var_values: + env_var_values[f'METPLUS_{loop_by}_BEG'] = ( + f'{loop_by.lower()}_beg = "{run_times[0]}";' + ) + remove_beg = True + + if f'METPLUS_{loop_by}_END' not in env_var_values: + env_var_values[f'METPLUS_{loop_by}_END'] = ( + f'{loop_by.lower()}_end = "{run_times[-1]}";' + ) + remove_end = True + + wrapper = TCPairsWrapper(config) + assert wrapper.isOK + + app_path = os.path.join(config.getdir('MET_BIN_DIR'), wrapper.app_name) + verbosity = f"-v {wrapper.c_dict['VERBOSITY']}" + config_file = wrapper.c_dict.get('CONFIG_FILE') + out_dir = wrapper.c_dict.get('OUTPUT_DIR') + expected_cmds = [(f"{app_path} {verbosity} " + f"-bdeck {bdeck_dir}/bmlq2014123118.gfso.0104 " + f"-adeck {adeck_dir}/amlq2014123118.gfso.0104 " + f"-config {config_file} " + f"-out {out_dir}/mlq2014121318.gfso.0104"), + ] + + + all_cmds = wrapper.run_all_times() + print(f"ALL COMMANDS: {all_cmds}") + assert(len(all_cmds) == len(expected_cmds)) + + for (cmd, env_vars), expected_cmd in zip(all_cmds, expected_cmds): + # ensure commands are generated as expected + assert(cmd == expected_cmd) + + # check that environment variables were set properly + for env_var_key in wrapper.WRAPPER_ENV_VAR_KEYS: + match = next((item for item in env_vars if + item.startswith(env_var_key)), None) + assert(match is not None) + print(f'Checking env var: {env_var_key}') + actual_value = match.split('=', 1)[1] + assert(env_var_values.get(env_var_key, '') == actual_value) + + if remove_beg: + del env_var_values[f'METPLUS_{loop_by}_BEG'] + if remove_end: + del env_var_values[f'METPLUS_{loop_by}_END'] @pytest.mark.parametrize( 'config_overrides, env_var_values', [ @@ -433,61 +446,68 @@ def test_tc_pairs_loop_order_processes(metplus_config, config_overrides, ) def test_tc_pairs_read_all_files(metplus_config, config_overrides, env_var_values): + # run using init and valid time variables + for loop_by in ['INIT', 'VALID']: + config = metplus_config() - config = metplus_config() + set_minimum_config_settings(config, loop_by) - set_minimum_config_settings(config) + test_data_dir = os.path.join(config.getdir('METPLUS_BASE'), + 'internal_tests', + 'data', + 'tc_pairs') + bdeck_dir = os.path.join(test_data_dir, 'bdeck') + adeck_dir = os.path.join(test_data_dir, 'adeck') - test_data_dir = os.path.join(config.getdir('METPLUS_BASE'), - 'internal_tests', - 'data', - 'tc_pairs') - bdeck_dir = os.path.join(test_data_dir, 'bdeck') - adeck_dir = os.path.join(test_data_dir, 'adeck') + config.set('config', 'TC_PAIRS_BDECK_INPUT_DIR', bdeck_dir) + config.set('config', 'TC_PAIRS_ADECK_INPUT_DIR', adeck_dir) - config.set('config', 'TC_PAIRS_BDECK_INPUT_DIR', bdeck_dir) - config.set('config', 'TC_PAIRS_ADECK_INPUT_DIR', adeck_dir) + # LOOP_ORDER processes runs once, times runs once per time + config.set('config', 'LOOP_ORDER', 'processes') - # LOOP_ORDER processes runs once, times runs once per time - config.set('config', 'LOOP_ORDER', 'processes') - - config.set('config', 'TC_PAIRS_READ_ALL_FILES', True) - config.set('config', 'TC_PAIRS_OUTPUT_TEMPLATE', '') + config.set('config', 'TC_PAIRS_READ_ALL_FILES', True) + config.set('config', 'TC_PAIRS_OUTPUT_TEMPLATE', '') - # set config variable overrides - for key, value in config_overrides.items(): - config.set('config', key, value) + # set config variable overrides + for key, value in config_overrides.items(): + config.set('config', key, value) - if 'METPLUS_INIT_BEG' not in env_var_values: - env_var_values['METPLUS_INIT_BEG'] = f'init_beg = "{run_times[0]}";' - - if 'METPLUS_INIT_END' not in env_var_values: - env_var_values['METPLUS_INIT_END'] = f'init_end = "{run_times[-1]}";' + env_var_values[f'METPLUS_{loop_by}_BEG'] = ( + f'{loop_by.lower()}_beg = "{run_times[0]}";' + ) - wrapper = TCPairsWrapper(config) - assert(wrapper.isOK) - - app_path = os.path.join(config.getdir('MET_BIN_DIR'), wrapper.app_name) - verbosity = f"-v {wrapper.c_dict['VERBOSITY']}" - config_file = wrapper.c_dict.get('CONFIG_FILE') - out_dir = wrapper.c_dict.get('OUTPUT_DIR') - expected_cmds = [(f"{app_path} {verbosity} " - f"-bdeck {bdeck_dir} " - f"-adeck {adeck_dir} " - f"-config {config_file} " - f"-out {out_dir}/tc_pairs"), - ] + env_var_values[f'METPLUS_{loop_by}_END'] = ( + f'{loop_by.lower()}_end = "{run_times[-1]}";' + ) - all_cmds = wrapper.run_all_times() - print(f"ALL COMMANDS: {all_cmds}") - assert(len(all_cmds) == len(expected_cmds)) - - for (cmd, env_vars), expected_cmd in zip(all_cmds, expected_cmds): - # check that environment variables were set properly - for env_var_key in wrapper.WRAPPER_ENV_VAR_KEYS: - match = next((item for item in env_vars if - item.startswith(env_var_key)), None) - assert(match is not None) - print(f'Checking env var: {env_var_key}') - actual_value = match.split('=', 1)[1] - assert(env_var_values.get(env_var_key, '') == actual_value) + wrapper = TCPairsWrapper(config) + assert wrapper.isOK + + app_path = os.path.join(config.getdir('MET_BIN_DIR'), wrapper.app_name) + verbosity = f"-v {wrapper.c_dict['VERBOSITY']}" + config_file = wrapper.c_dict.get('CONFIG_FILE') + out_dir = wrapper.c_dict.get('OUTPUT_DIR') + expected_cmds = [(f"{app_path} {verbosity} " + f"-bdeck {bdeck_dir} " + f"-adeck {adeck_dir} " + f"-config {config_file} " + f"-out {out_dir}/tc_pairs"), + ] + + all_cmds = wrapper.run_all_times() + print(f"ALL COMMANDS: {all_cmds}") + assert(len(all_cmds) == len(expected_cmds)) + + for (cmd, env_vars), expected_cmd in zip(all_cmds, expected_cmds): + # check that environment variables were set properly + for env_var_key in wrapper.WRAPPER_ENV_VAR_KEYS: + match = next((item for item in env_vars if + item.startswith(env_var_key)), None) + assert(match is not None) + print(f'Checking env var: {env_var_key}') + actual_value = match.split('=', 1)[1] + assert(env_var_values.get(env_var_key, '') == actual_value) + + # unset begin and end for next loop + del env_var_values[f'METPLUS_{loop_by}_BEG'] + del env_var_values[f'METPLUS_{loop_by}_END'] diff --git a/metplus/wrappers/command_builder.py b/metplus/wrappers/command_builder.py index c6c802ca9b..5d2b8642fd 100755 --- a/metplus/wrappers/command_builder.py +++ b/metplus/wrappers/command_builder.py @@ -2283,3 +2283,23 @@ def get_met_config(self, **kwargs): @returns METConfigInfo object """ return met_config(**kwargs) + + def get_start_time_input_dict(self): + """! Get the first run time specified in config. Used if only running + the wrapper once (LOOP_ORDER = processes). + + @returns dictionary containing time information for first run time + """ + use_init = util.is_loop_by_init(self.config) + if use_init is None: + self.log_error('Could not read time info') + return None + + + start_time, _, _ = util.get_start_end_interval_times(self.config) + if start_time is None: + self.log_error("Could not get start time") + return None + + input_dict = util.set_input_dict(start_time, self.config, use_init) + return input_dict diff --git a/metplus/wrappers/tc_pairs_wrapper.py b/metplus/wrappers/tc_pairs_wrapper.py index a82cea3ffc..ea2ad16b5a 100755 --- a/metplus/wrappers/tc_pairs_wrapper.py +++ b/metplus/wrappers/tc_pairs_wrapper.py @@ -150,19 +150,8 @@ def create_c_dict(self): self.handle_consensus() - init_time_fmt = self.config.getstr('config', 'INIT_TIME_FMT') - clock_time = datetime.datetime.strptime( - self.config.getstr('config', - 'CLOCK_TIME'), - '%Y%m%d%H%M%S' - ) - - init_beg = self.config.getraw('config', 'INIT_BEG') - init_beg_dt = util.get_time_obj(init_beg, - init_time_fmt, - clock_time, - logger=self.logger) - c_dict['INIT_BEG'] = init_beg_dt.strftime('%Y%m%d_%H%M%S') + # if looping by processes, get the init or valid beg time and run once + c_dict['INPUT_DICT'] = self.get_start_time_input_dict() c_dict['INIT_INCLUDE'] = util.getlist( self.get_wrapper_or_generic_config('INIT_INCLUDE') @@ -256,6 +245,12 @@ def create_c_dict(self): self.handle_description() + c_dict['SKIP_LEAD_SEQ'] = ( + self.config.getbool('config', + 'TC_PAIRS_SKIP_LEAD_SEQ', + False) + ) + return c_dict def _read_storm_info(self, c_dict): @@ -360,11 +355,8 @@ def handle_consensus(self): def run_all_times(self): """! Build up the command to invoke the MET tool tc_pairs. """ - # use init begin as run time (start of the storm) - input_dict = {'init': - datetime.datetime.strptime(self.c_dict['INIT_BEG'], - '%Y%m%d_%H%M%S') - } + # use first run time + input_dict = self.c_dict.get('INPUT_DICT') # if running in READ_ALL_FILES mode, call tc_pairs once and exit if self.c_dict['READ_ALL_FILES']: @@ -385,12 +377,22 @@ def run_at_time(self, input_dict): self.logger.info(f"Processing custom string: {custom_string}") input_dict['custom'] = custom_string - time_info = time_util.ti_calculate(input_dict) - if util.skip_time(time_info, self.c_dict.get('SKIP_TIMES', {})): - self.logger.debug('Skipping run time') - return - self.run_at_time_loop_string(time_info) + # if skipping lead sequence, only run once per init/valid time + if self.c_dict['SKIP_LEAD_SEQ']: + lead_seq = [0] + else: + lead_seq = util.get_lead_sequence(self.config, input_dict) + + for lead in lead_seq: + input_dict['lead'] = lead + time_info = time_util.ti_calculate(input_dict) + + if util.skip_time(time_info, self.c_dict.get('SKIP_TIMES', {})): + self.logger.debug('Skipping run time') + return + + self.run_at_time_loop_string(time_info) def run_at_time_loop_string(self, time_info): """! Create the arguments to run MET tc_pairs @@ -536,10 +538,7 @@ class attributes # add storm month to each cyclone item if reformatting SBU if self.c_dict['REFORMAT_DECK'] and \ self.c_dict['REFORMAT_DECK_TYPE'] == 'SBU': - if time_info is None: - storm_month = self.c_dict['INIT_BEG'][4:6] - else: - storm_month = time_info['init'].strftime('%m') + storm_month = time_info['init'].strftime('%m') cyclone = [storm_month + c for c in cyclone] cyclone = str(cyclone).replace("'", '"') @@ -634,7 +633,7 @@ def process_data(self, basin, cyclone, time_info): return [] # Set up the environment variable to be used in the TCPairs Config - self.set_environment_variables(time_info) + self.set_environment_variables(time_storm_info) self.build() @@ -911,7 +910,7 @@ def _read_all_files(self, input_dict): directories to search for files to let the application determine which data to process - @param input_dict dictionary containing init time set from INIT_BEG + @param input_dict dictionary containing some time information @returns list of tuples containing commands that are run and which env vars were set for the command """ @@ -939,7 +938,7 @@ def _read_all_files(self, input_dict): check_extension='.tcst'): return [] - self.set_environment_variables(input_dict) + self.set_environment_variables(time_storm_info) self.build() return self.all_commands diff --git a/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_extra_tropical.conf b/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_extra_tropical.conf index c9060fb8a5..cdbc4d633a 100644 --- a/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_extra_tropical.conf +++ b/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_extra_tropical.conf @@ -38,6 +38,10 @@ TC_PAIRS_INIT_END = {INIT_END} TC_PAIRS_VALID_BEG = TC_PAIRS_VALID_END = +# Skip looping over forecast leads if a list is provided +#TC_PAIRS_SKIP_LEAD_SEQ = False + + ## # # MET TC-Pairs diff --git a/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_tropical.conf b/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_tropical.conf index bf1a8a67ae..a7192ecba8 100644 --- a/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_tropical.conf +++ b/parm/use_cases/met_tool_wrapper/TCPairs/TCPairs_tropical.conf @@ -22,7 +22,7 @@ INIT_END = 2018083018 # This is the step-size. Increment in seconds from the begin time to the end time # set to 6 hours = 21600 seconds -INIT_INCREMENT = 21600 +INIT_INCREMENT = 21600 # A list of times to include, in format YYYYMMDD_hh TC_PAIRS_INIT_INCLUDE = @@ -54,6 +54,10 @@ TC_PAIRS_REFORMAT_DECK = no # Set to no if you do want to override existing files TC_PAIRS_SKIP_IF_OUTPUT_EXISTS = no +# Skip looping over forecast leads if a list is provided +#TC_PAIRS_SKIP_LEAD_SEQ = False + + # # MET TC-Pairs # diff --git a/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead.conf b/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead.conf index 8bbfa04dc9..607cce7caf 100644 --- a/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead.conf +++ b/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead.conf @@ -39,11 +39,12 @@ LEAD_SEQ_2 = begin_end_incr(24,42,6) # forecast lead sequence 2 label LEAD_SEQ_2_LABEL = Day2 - ####### # TCPairs Configurations ####### +TC_PAIRS_SKIP_LEAD_SEQ = True + # A list of times to include, in format YYYYMMDD_hh TC_PAIRS_INIT_INCLUDE = diff --git a/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_IVT.conf b/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_IVT.conf index eb8904dff4..c5e864e7e1 100644 --- a/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_IVT.conf +++ b/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_IVT.conf @@ -73,6 +73,9 @@ PY_EMBED_INGEST_2_OUTPUT_FIELD_NAME = ivt # TCPairs Configurations ####### +# only run TCPairs once for the init time, not for each forecast lead +TC_PAIRS_SKIP_LEAD_SEQ = True + # A list of times to include, in format YYYYMMDD_hh TC_PAIRS_INIT_INCLUDE = diff --git a/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_Multiple_Diagnostics.conf b/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_Multiple_Diagnostics.conf index 4fd5735963..0751ca521d 100644 --- a/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_Multiple_Diagnostics.conf +++ b/parm/use_cases/model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByLead_PyEmbed_Multiple_Diagnostics.conf @@ -87,6 +87,9 @@ PY_EMBED_INGEST_2_OUTPUT_GRID = {MODEL_DIR}/{valid?fmt=%Y%m%d}/gfs_4_{valid?fmt= # TCPairs Configurations ####### +# only run TCPairs once for the init time, not for each forecast lead +TC_PAIRS_SKIP_LEAD_SEQ = True + # A list of times to include, in format YYYYMMDD_hh TC_PAIRS_INIT_INCLUDE =