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']
Exemple #4
0
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)