def fit(self, bounds=None, start=None):
        """Fit incidence function parameters."""

        start_vals = start['beta'].flatten()
        bound_vals = bounds['beta'].flatten().reshape((4, 2))

        start_transformed = fitting.logit_transform(start_vals, bound_vals)

        init_state = np.sum(self.parent_fitter.parent_fitter.data['init_state'][0].reshape((3, 6)),
                            axis=0)

        model_params = {
            'birth_rate': self.parent_fitter.parent_fitter.sim_params['birth_rate'],
            'death_rate': self.parent_fitter.parent_fitter.sim_params['death_rate'],
            'removal_rate': self.parent_fitter.parent_fitter.sim_params['removal_rate'],
            'recov_rate': self.parent_fitter.parent_fitter.sim_params['recov_rate'],
            'state_init': init_state,
            'times': self.parent_fitter.parent_fitter.data['dpc_times'],
            'max_control_rate': 0,
            'high_alloc_cost': 0,
            'low_alloc_cost': 0
        }
        model = risk_model.RiskModel(model_params, self)

        # Minimise SSE
        param_fit_transformed = minimize(
            self.sse, start_transformed, method="L-BFGS-B", options={'ftol': 1e-12},
            args=(bound_vals, model))

        param_fit = fitting.reverse_logit_transform(param_fit_transformed.x, bound_vals)

        self.data['beta'] = np.array(param_fit).reshape((2, 2))
    def fit(self, bounds=None, start=None):
        """Fit incidence function parameters."""

        # Fit parameters associated with each risk group separately since log likelihood separates
        for risk in Risk:
            start_vals = start['beta'][risk]
            bound_vals = bounds['beta'][risk]

            param_dict_tmp = {
                'beta': np.zeros((2, 2))
            }

            start_transformed = fitting.logit_transform(start_vals, bound_vals)

            def neg_loglik(params, risk, bounds, param_dict):
                """Calculate negative log likelihood from transformed optimisation parameters."""
                # First reverse logit transform parameters
                _params_rev_trans = fitting.reverse_logit_transform(params, bounds)
                param_dict['beta'][risk] = _params_rev_trans
                val = self._calc_likelihood(param_dict, [risk])

                return np.nan_to_num(-val)

            # Minimise negative log likelihood
            param_fit_transformed = minimize(
                neg_loglik, start_transformed, method="L-BFGS-B", options={'ftol': 1e-12},
                args=(risk, bound_vals, param_dict_tmp))

            param_fit = fitting.reverse_logit_transform(param_fit_transformed.x, bound_vals)

            if 'beta' not in self.data:
                self.data['beta'] = np.zeros((2, 2))

            self.data['beta'][risk] = param_fit
    def sse(self, params, bounds, model):
        """Calculate sum squared errors from transformed optimisation parameters."""
        # First reverse logit transform parameters
        _params_rev_trans = fitting.reverse_logit_transform(params, bounds)
        self.data['sigma'][[0, 1, 1, 2, 2],
                           [0, 0, 1, 1, 2]] = _params_rev_trans[0:5]
        self.data['rho'][[0, 1, 1], [1, 0, 1]] = _params_rev_trans[5:]

        # Run ODE model with parameters
        ode_run = model.run_policy(space_model.no_control_policy)

        dpc_data = self.parent_fitter.parent_fitter.data['dpc_inf']
        dpc_times = self.parent_fitter.parent_fitter.data['dpc_times']

        # Calculate SSE
        sse = 0
        for i in range(dpc_data.shape[3]):
            for region in range(3):
                sse += np.sum(
                    np.square(dpc_data[region, 0, :, i] - np.array(
                        [ode_run.state(t)[6 * region + 1]
                         for t in dpc_times])))
                sse += np.sum(
                    np.square(dpc_data[region, 1, :, i] - np.array(
                        [ode_run.state(t)[6 * region + 4]
                         for t in dpc_times])))
        return sse
            def neg_loglik(params, risk, bounds, param_dict):
                """Calculate negative log likelihood from transformed optimisation parameters."""
                # First reverse logit transform parameters
                _params_rev_trans = fitting.reverse_logit_transform(params, bounds)
                param_dict['beta'][risk] = _params_rev_trans
                val = self._calc_likelihood(param_dict, [risk])

                return np.nan_to_num(-val)
        def neg_loglik(params, bounds, param_dict):
            """Calculate neg log likelihood from transformed optimisation parameters."""
            # First reverse logit transform parameters
            _params_rev_trans = fitting.reverse_logit_transform(params, bounds)
            param_dict['sigma'][[0, 1, 1, 2, 2],
                                [0, 0, 1, 1, 2]] = _params_rev_trans[0:5]
            param_dict['rho'][[0, 1, 1], [1, 0, 1]] = _params_rev_trans[5:]

            val = self._calc_likelihood(param_dict)
            return np.nan_to_num(-val)
    def fit(self, bounds=None, start=None):
        """Fit incidence function parameters."""

        nparams = 8

        start_vals = np.zeros(nparams)
        bound_vals = np.zeros((nparams, 2))

        start_vals[0:5] = start['sigma'].flatten()[[0, 3, 4, 7, 8]]
        bound_vals[0:5, :] = bounds['sigma'].reshape(9, 2)[[0, 3, 4, 7, 8]]

        start_vals[5:] = [
            start['rho'][0, 1], start['rho'][1, 0], start['rho'][1, 1]
        ]
        bound_vals[5:, :] = bounds['rho'].reshape(4, 2)[[1, 2, 3]]

        param_dict_tmp = {'sigma': np.zeros((3, 3)), 'rho': np.zeros((2, 2))}
        param_dict_tmp['rho'][0, 0] = 1
        param_dict_tmp['sigma'][0, 2] = 0
        param_dict_tmp['sigma'][2, 0] = 0
        param_dict_tmp['sigma'][0, 1] = 0
        param_dict_tmp['sigma'][1, 0] = 0

        start_transformed = fitting.logit_transform(start_vals, bound_vals)

        def neg_loglik(params, bounds, param_dict):
            """Calculate neg log likelihood from transformed optimisation parameters."""
            # First reverse logit transform parameters
            _params_rev_trans = fitting.reverse_logit_transform(params, bounds)
            param_dict['sigma'][[0, 1, 1, 2, 2],
                                [0, 0, 1, 1, 2]] = _params_rev_trans[0:5]
            param_dict['rho'][[0, 1, 1], [1, 0, 1]] = _params_rev_trans[5:]

            val = self._calc_likelihood(param_dict)
            return np.nan_to_num(-val)

        param_fit_transformed = minimize(neg_loglik,
                                         start_transformed,
                                         method="L-BFGS-B",
                                         options={'ftol': 1e-12},
                                         args=(bound_vals, param_dict_tmp))

        param_fit = fitting.reverse_logit_transform(param_fit_transformed.x,
                                                    bound_vals)

        if 'sigma' not in self.data:
            self.data['sigma'] = np.zeros((3, 3))
        if 'rho' not in self.data:
            self.data['rho'] = np.ones((2, 2))

        self.data['sigma'][[0, 1, 1, 2, 2], [0, 0, 1, 1, 2]] = param_fit[0:5]
        self.data['rho'][[0, 1, 1], [1, 0, 1]] = param_fit[5:]
    def sse(self, params, bounds, model):
        """Calculate sum squared errors from transformed optimisation parameters."""
        # First reverse logit transform parameters
        _params_rev_trans = fitting.reverse_logit_transform(params, bounds)
        self.data['beta'] = np.array(_params_rev_trans).reshape((2, 2))

        # Run ODE model with parameters
        ode_run = model.run_policy(risk_model.no_control_policy)

        dpc_data = self.parent_fitter.parent_fitter.data['dpc_inf']
        dpc_times = self.parent_fitter.parent_fitter.data['dpc_times']

        # Calculate SSE
        sse = 0
        for i in range(dpc_data.shape[3]):
            sse += np.sum(np.square(np.sum(
                dpc_data[:, 0, :, i], axis=0) - np.array([ode_run.state(t)[1] for t in dpc_times])))
            sse += np.sum(np.square(np.sum(
                dpc_data[:, 1, :, i], axis=0) - np.array([ode_run.state(t)[4] for t in dpc_times])))
        return sse
    def fit(self, bounds=None, start=None):
        """Fit incidence function parameters."""

        nparams = 8

        start_vals = np.zeros(nparams)
        bound_vals = np.zeros((nparams, 2))

        start_vals[0:5] = start['sigma'].flatten()[[0, 3, 4, 7, 8]]
        bound_vals[0:5, :] = bounds['sigma'].reshape(9, 2)[[0, 3, 4, 7, 8]]

        start_vals[5:] = [
            start['rho'][0, 1], start['rho'][1, 0], start['rho'][1, 1]
        ]
        bound_vals[5:, :] = bounds['rho'].reshape(4, 2)[[1, 2, 3]]

        self.data['sigma'] = np.zeros((3, 3), dtype=float)
        self.data['rho'] = np.ones((2, 2), dtype=float)

        start_transformed = fitting.logit_transform(start_vals, bound_vals)

        init_state = self.parent_fitter.parent_fitter.data['init_state'][0]

        model_params = {
            'birth_rate':
            self.parent_fitter.parent_fitter.sim_params['birth_rate'],
            'death_rate':
            self.parent_fitter.parent_fitter.sim_params['death_rate'],
            'removal_rate':
            self.parent_fitter.parent_fitter.sim_params['removal_rate'],
            'recov_rate':
            self.parent_fitter.parent_fitter.sim_params['recov_rate'],
            'state_init':
            init_state,
            'times':
            self.parent_fitter.parent_fitter.data['dpc_times'],
            'max_control_rate':
            0,
            'high_alloc_cost':
            0,
            'low_alloc_cost':
            0
        }
        model = space_model.SpaceModel(model_params, self)

        param_fit_transformed = minimize(self.sse,
                                         start_transformed,
                                         method="L-BFGS-B",
                                         options={'ftol': 1e-12},
                                         args=(bound_vals, model))

        param_fit = fitting.reverse_logit_transform(param_fit_transformed.x,
                                                    bound_vals)

        if 'sigma' not in self.data:
            self.data['sigma'] = np.zeros((3, 3), dtype=float)
        if 'rho' not in self.data:
            self.data['rho'] = np.ones((2, 2), dtype=float)

        self.data['sigma'][[0, 1, 1, 2, 2], [0, 0, 1, 1, 2]] = param_fit[0:5]
        self.data['rho'][[0, 1, 1], [1, 0, 1]] = param_fit[5:]