def create_scenarios(exp, scen_df):
"""
Creates OpenMalaria simulation scenarios based on a dataframe containing scenario parameters.
This function generates multiple OpenMalaria scenario XML files by replacing placeholders in a template
XML with specific parameters from the experiment configuration and scenario dataframe. Each scenario is
customized based on the parameters from the dataframe, and the resulting XML files are saved to the job directory.
Args:
exp (Experiment): The experiment object containing configuration parameters such as OpenMalaria version,
population size, simulation years, entomology mode, and other parameters required for
generating the scenarios.
scen_df (pandas.DataFrame): A dataframe containing scenario parameters such as seed values, clinical malaria
data, and other model-specific inputs.
Returns:
None
"""
with open(os.path.join(exp.openmalaria_input_path, 'scaffolds', f"{exp.openmalaria_scaffold}.xml"), "r") as fp:
xml = fp.read()
exp.days_between_clinical_cases_5days = 5 # Aurelien communicated that as long as we use v46, we should have a days_between_clinical_cases of 25 days
# Replace placeholders in the XML template with fixed parameters
xml = xml.replace("@version@", f"{exp.openmalaria_version}")
xml = xml.replace("@pop_size@", f"{exp.openmalaria_pop_size}")
xml = xml.replace("@burnin_start_year@", f"{exp.sim_start_year_openmalaria}")
xml = xml.replace("@start_year@", f"{exp.start_year - 1}")
xml = xml.replace("@end_year@", f"{exp.end_year - 1}")
xml = xml.replace("@survey_step@", f"{exp.openmalaria_survey_step}")
xml = xml.replace("@entomology_mode@", f"{exp.entomology_mode}")
xml = xml.replace("@detectionLimit@", f"{exp.detectionLimit}")
xml = xml.replace('@importation_rate@', f"{exp.importation_rate}")
xml = xml.replace('@healthSystemMemory@', f"{str(int(exp.days_between_clinical_cases_5days))}")
xmlageGroups = '\t\t<ageGroup lowerbound="0">'
for item in exp.agebins:
xmlageGroups += f'\n\t\t\t<group upperbound="{item}"/>'
xml = xml.replace('<@age_groups@>', xmlageGroups)
# Scenario sweeps and runs
df = rep_scen_df(scen_df)
for r, row in df.iterrows():
if row['cm_clinical'] == 0.45:
cm_clinical_5daily = 0.209261
elif row['cm_clinical'] == 0.15:
cm_clinical_5daily = 0.05161556
elif row['cm_clinical'] == 0:
cm_clinical_5daily = 0
else:
raise ValueError('convert_access for OpenMalaria cm_clinical currently not functional')
# cm_clinical_5daily = convert_access(row['cm_clinical']) # TODO convert from R function to python
scenario = xml.replace('@seed@', str(row['seed']))
scenario = scenario.replace('@cm_clinical@', str(cm_clinical_5daily))
scenario = scenario.replace('@cm_severe@', str(row['cm_severe']))
scenario = scenario.replace('@eir@', str(row['model_input_openmalaria']))
if 'cc_step' in exp.intervention_list:
scenario = scenario.replace('@EIR_reduction@', str(row['cc_factor_openmalaria']))
scenario = scenario.replace('@step_change_time@', str(row['cc_timestep_openmalaria']))
#SMC currently not supported
#if 'smc' in exp.intervention_list:
# scenario = write_smc_deployment(scenario, row)
seasonality = getattr(exp, row['seasonality'])
# Replace seasonality placeholders with corresponding values from the experiment object
for i in range(1, 13):
scenario = scenario.replace(f'@seasonality{i}@', str(seasonality[i - 1]))
# Write the scenario XML file
with open(f"{exp.job_directory}/xml/{row['index']}.xml", 'w') as fo:
fo.write(f"{scenario}")
# Copy additional files required by OpenMalaria
shutil.copy(exp.openmalaria_path + "/densities.csv", f"{exp.job_directory}/")
schema = f"scenario_{exp.openmalaria_version}.xsd"
shutil.copy(os.path.join(exp.openmalaria_path, schema), exp.job_directory)