def test_aggregate_fitting(self): """Test fitting when simulation hosts aggregated to reduced resolution.""" centre = [3*int(x / 2)+1 for x in self._size] new_size = [(int(x / 2) + 1) for x in self._size] start = [int(cen - (3*n-1)/2) for cen, n in zip(centre, new_size)] raster_header = { 'nrows': new_size[0], 'ncols': new_size[1], 'xllcorner': start[0], 'yllcorner': start[1], 'cellsize': 3, 'NODATA_value': -9999 } print(raster_header) # Fully precalculate likelihood function for exponential kernel lik_func = rmf.precompute_loglik(data_stub=self._data_stub, nsims=None, raster_header=raster_header, precompute_level="full", ignore_outside_raster=True) # Fit using MLE fitted_params, raw_output = rmf.fit_raster_MLE( self._spatial_generator, {"beta": [0, 50], "scale": [0, 10]}, likelihood_func=lik_func, kernel_jac=self._spatial_jac_generator, raw_output=True, param_start={'beta':4, 'scale':0.2}) print(fitted_params, raw_output) # Assert beta and scale values are close to those used in simulation # Specifically allow 10% for beta since data subsetting will result in overestimation if self.do_asserts: self.assertTrue(abs((self._beta_val-fitted_params['beta'])/self._beta_val) < 0.1) self.assertTrue(abs((self._scale_val-3*fitted_params['scale'])/self._scale_val) < 0.05)
def test_non_spatial_full(self): """Test full likelihood precalculation and MLE fitting for non-spatial test case.""" # Fully precalculate likelihood function for non-spatial kernel (i.e. beta) lik_func = rmf.precompute_loglik(data_stub=self._data_stub, nsims=None, raster_header=self._raster_header, precompute_level="full") # Fit using MLE fitted_params = rmf.fit_raster_MLE( self._nonspatial_generator, {"beta": [0, 0.1]}, likelihood_func=lik_func, kernel_jac=self._nonspatial_jac_generator) # Assert beta value is close to that used in simulation if self.do_asserts: self.assertTrue(abs((self._beta_val-fitted_params['beta'])/self._beta_val) < 0.01) return fitted_params["beta"]
def test_spatial_partial(self): """Test partial likelihood precalculation and MLE fitting for spatial test case.""" # Fully precalculate likelihood function for exponential kernel lik_func = rmf.precompute_loglik( data_stub=self._data_stub, nsims=None, raster_header=self._raster_header, precompute_level="partial", end_time=self._end_time) # Fit using MLE fitted_params, raw_output = rmf.fit_raster_MLE( self._spatial_generator, {"beta": [0, 20], "scale": [0, 10]}, likelihood_func=lik_func, kernel_jac=self._spatial_jac_generator, raw_output=True, param_start={'beta':8, 'scale':0.2}) print(fitted_params, raw_output) # Assert beta and scale values are close to those used in simulation if self.do_asserts: self.assertTrue(abs((self._beta_val-fitted_params['beta'])/self._beta_val) < 0.05) self.assertTrue(abs((self._scale_val-fitted_params['scale'])/self._scale_val) < 0.05) return fitted_params['beta'], fitted_params['scale']
def fit_landscapes(out_file, config_dict, test_resolutions, full_resolution, sim_stub, append=False): """Fit raster model kernel parameters to simulation data.""" if append: try: with open(out_file, "r") as fin: all_fit_results = json.load(fin) except FileNotFoundError: logging.warning("FitResults file not found! Starting new results.") all_fit_results = {} else: all_fit_results = {} for i, resolution in enumerate(test_resolutions): logging.info("Starting fit for %dm resolution.", resolution) landscape_name = "ROI_" + str(resolution) + "Landscape" raster_header = raster_tools.RasterData.from_file( os.path.join("GeneratedData", landscape_name, "HostNumbers.txt")).header_vals kernel_names = OPTIONS['kernel_names'] sus_inf_file = os.path.join("GeneratedData", landscape_name, "RMSMask.txt") kernel_generators = [] kernel_jac_generators = [] for name in kernel_names: if name == "Exponential": kernel_generators.append(kernels.make_exponential_kernel) kernel_jac_generators.append(kernels.make_exponential_jac) elif name == "Cauchy": kernel_generators.append(kernels.make_cauchy_kernel) kernel_jac_generators.append(kernels.make_cauchy_jac) elif name == "ExpPower": kernel_generators.append(kernels.make_exp_power_kernel) kernel_jac_generators.append(kernels.make_exp_power_jac) else: raise ValueError("Unknown kernel name!") fit_method = OPTIONS['fit_method'] if fit_method == "MLE": likelihood_id = config_dict['resolution_testing_options'][ 'fit_landscapes']['likelihood_id'] if likelihood_id is None: save_file = os.path.join("GeneratedData", "SimulationRuns", landscape_name + "_likelihood.npz") else: save_file = os.path.join( "GeneratedData", "SimulationRuns", landscape_name + "_likelihood_" + likelihood_id + ".npz") lik_loaded = raster_model_fitting.LikelihoodFunction.from_file( save_file) elif fit_method == "SSE": # Check if simulation summaries have been generated if not os.path.isfile( os.path.join(sim_stub, "summaries", landscape_name + '.h5')): # If not then summarise simulations at this resolution summarise_sims.summarise_sims( target_header=raster_header, region=MainOptions.OPTIONS['roi'], sim_stub=sim_stub, landscape_name=landscape_name) zipped_values = zip(kernel_names, kernel_generators, kernel_jac_generators) for j, (name, gen, jac) in enumerate(zipped_values): prior = OPTIONS['kernel_priors'][i][j] start = OPTIONS['kernel_inits'][i][j] primary_rate = bool("PrimaryRate" in prior) if fit_method == "MLE": opt_params, fit_output = raster_model_fitting.fit_raster_MLE( data_stub=sim_stub, kernel_generator=gen, kernel_params=prior, param_start=start, target_raster=raster_header, nsims=None, likelihood_func=lik_loaded, kernel_jac=jac, raw_output=True, primary_rate=primary_rate) elif fit_method == "SSE": model_params = { 'inf_rate': 1.0, 'control_rate': 0, 'coupling': np.zeros((raster_header['nrows'], raster_header['ncols'])), 'times': MainOptions.OPTIONS['times'], 'max_hosts': int(100 * np.power(resolution / full_resolution, 2)), 'primary_rate': 0 } sim_sum_file = os.path.join(sim_stub, "summaries", landscape_name + ".h5") host_file = os.path.join("GeneratedData", landscape_name, "HostDensity.txt") s_init_file = os.path.join("GeneratedData", landscape_name, "InitialConditions_Density_S.txt") i_init_file = os.path.join("GeneratedData", landscape_name, "InitialConditions_Density_I.txt") model = raster_model.RasterModel(model_params, host_density_file=host_file, initial_s_file=s_init_file, initial_i_file=i_init_file) opt_params, fit_output = raster_model_fitting.fit_raster_SSE( model=model, kernel_generator=gen, kernel_params=prior, data_path=sim_sum_file, param_start=start, n_sims=None, target_header=raster_header, raw_output=True, primary_rate=primary_rate, sus_file=sus_inf_file, inf_file=sus_inf_file) else: raise ValueError("Unrecognised fit method!") logging.info("Optimisation completed %s %s %s", landscape_name, name, opt_params) opt_params['Raw_Output'] = fit_output.__repr__() opt_params['Prior'] = prior opt_params['Initialisation'] = start # Save results if landscape_name in all_fit_results: all_fit_results[landscape_name][name] = opt_params else: all_fit_results[landscape_name] = {name: opt_params} with open(out_file, "w") as f_out: json.dump(all_fit_results, f_out, indent=4) logging.info("Fit for %dm resolution complete.", resolution)