import os
from pathlib import Path
from idmtools.assets import AssetCollection
from idmtools_calibra.calib_manager import CalibManager
from idmtools_calibra.algorithms.optim_tool import OptimTool
from idmtools_calibra.plotters.likelihood_plotter import LikelihoodPlotter
from idmtools_calibra.plotters.optim_tool_plotter import OptimToolPlotter
from idmtools_calibra.plotters.site_data_plotter import SiteDataPlotter
from idmtools.core.platform_factory import Platform
from idmtools.entities import CommandLine
from idmtools_calibra.singularity_json_python_task import SingularityJSONConfiguredPythonTask as Task
from idmtools_models.python.json_python_task import JSONConfiguredPythonTask
params = None # hack block
campaign_builder_fn = None
demog_builder_fn = None
[docs]def constrain_sample(sample):
"""
This function is called on every samples and allow the user to edit them before they are passed
to the map_sample_to_model_input function.
It is useful to round some parameters as demonstrated below.
#Can do much more here, e.g. for
Clinical Fever Threshold High < MSP1 Merozoite Kill Fraction
if 'Clinical Fever Threshold High' and "MSP1 Merozoite Kill Fraction" in sample:
sample['Clinical Fever Threshold High'] = \
min( sample['Clinical Fever Threshold High'], sample['MSP1 Merozoite Kill Fraction'] ).
You can omit this function by not specifying it in the OptimTool constructor call below.
Args:
sample: The sample coming from the next point algorithm
Returns: The sample with constrained values
"""
return sample
campaign_mapper = None
demog_mapper = None
[docs]def init(settings, site, task=None, platform=None):
# the object representing the resource we will use for running simulations
global params
params = settings
if not platform:
print( "No platform specified. Creating Platform with Normal proirity." )
platform = Platform(settings.LOCALE, priority="Normal")
# If any directories of files were specified to be added as assets of the simulations, add them now.
assets = AssetCollection()
for directory in settings.INPUT_DIRS:
assets.add_directory(directory, relative_path=os.path.basename(directory))
if task is None:
command = None
if "SIF" in settings.__dict__:
assets.add_assets(AssetCollection.from_id(item_id=settings.SIF))
command = CommandLine(
f"singularity exec ./Assets/{settings.SIF_FILENAME} python3 Assets/{Path(settings.MODEL_DRIVER).name}"
)
task = Task(
provided_command=command,
script_path=str(settings.MODEL_DRIVER),
common_assets=assets,
config_file_name=settings.CONFIG_FILENAME
)
else:
#print( '"SIF" not found in settings."' )
command = CommandLine(
f"python3 Assets/{Path(settings.MODEL_DRIVER).name}"
)
task = JSONConfiguredPythonTask(script_path=str(settings.MODEL_DRIVER), common_assets=assets,
config_file_name=settings.CONFIG_FILENAME)
task.provided_command = command
#print( str( command ) )
# The task object defines what to run, how, and what assets will be associated with an experiment of simulations
# Each calibration iteration will run one experiment (group of simulations)
# The default plotters used in an Optimization with OptimTool
plotters = [
LikelihoodPlotter(combine_sites=True),
SiteDataPlotter(num_to_plot=settings.num_to_plot, combine_sites=True),
OptimToolPlotter(), # OTP must be last because it calls gc.collect()
]
# desired fraction of N-sphere area to unit cube area for numerical derivative (automatic radius scaling with N)
n_dynamic_parameters = len(
[p for p in settings.CALIBRATION_PARAMETERS if p["Dynamic"]]
)
if n_dynamic_parameters == 0:
warning_note = """
/!\\ WARNING /!\\ OptimTool requires at least one dynamic parameter ('Dynamic' set to True). Exiting ...
"""
print(warning_note)
exit()
r = OptimTool.get_r(n_dynamic_parameters, settings.volume_fraction)
# Here we combine all the inputs above to configure OptimTool (our next point algorithm) and the CalibManager
# (the object that will drive the calibration).
optimtool = OptimTool(
settings.CALIBRATION_PARAMETERS,
constrain_sample,
rsquared_thresh=0.81,
mu_r=r, # <-- radius for numerical derivatve. CAREFUL not to go too small with integer parameters
sigma_r=r / 10.0, # <-- stdev of radius
# this many samples will be repetitions of the existing best-sample (with
# different run numbers)
center_repeats=2,
# Samples per iteration, includes center repeats.
# Actual number of sims run is this number times number of replicates.
samples_per_iteration=settings.N_SAMPLES,
)
calib_manager = CalibManager(
name=settings.CALIBRATION_NAME,
task=task,
map_sample_to_model_input_fn=map_sample_to_model_input,
sites=[site],
next_point=optimtool,
sim_runs_per_param_set=settings.N_REPLICATES,
# <-- Number of times to replicate the center (current guess). For comparing intrinsic and extrinsic variability.
max_iterations=settings.N_ITERATIONS, # <-- number of iterations to run
plotters=plotters,
)
calib_manager.platform = platform
return calib_manager
[docs]def go(calib_manager, **kwargs):
calib_manager.run_calibration(**kwargs)