Ejemplo n.º 1
0
 def objective_function(self, fps, *args):
     model, weights, inputs, meas = args
     _fitter_to_model_params(model, fps)
     if weights is None:
         return np.ravel(np.subtract(model(*inputs), meas))
     else:
         return np.ravel(weights * np.subtract(model(*inputs), meas))
Ejemplo n.º 2
0
    def __call__(self,
                 model,
                 x,
                 measured_raw_cts,
                 measured_bkg_cts,
                 t_raw,
                 t_bkg,
                 x_err=None,
                 **kwargs):
        if x_err is not None:
            model = IntModel(model.__class__)(x_err, *model.parameters)

        model_copy = _validate_model(model, self.supported_constraints)
        farg = _convert_input(x, measured_raw_cts)
        farg = (model_copy, measured_bkg_cts, t_raw, t_bkg) + farg
        p0, _ = _model_to_fit_params(model_copy)

        # TODO: Honor estimate_jacobian in kwargs, and/or determine if
        # model supports jacobian, and/or if fitter supports the jac argument.

        fitparams, self.fit_info = self._opt_method(
            self.objective_function,
            p0,
            farg,
            jac=self.objective_derivative,
            **kwargs)
        _fitter_to_model_params(model_copy, fitparams)

        return model_copy
Ejemplo n.º 3
0
    def __call__(self, model, in_coords, ref_coords, sigma=5.0, maxsig=4.0,
                 **kwargs):
        model_copy = _validate_model(model, ['bounds'])
        x, y = in_coords
        xref, yref = ref_coords
        xmax = max(np.max(x), np.max(xref))
        ymax = max(np.max(y), np.max(yref))
        landscape = self.mklandscape(ref_coords, sigma, maxsig,
                                    (int(ymax),int(xmax)))
        farg = (model_copy,) + _convert_input(x, y, landscape)
        p0, _ = _model_to_fit_params(model_copy)

        # TODO: Use the name of the parameter to infer the step size
        ranges = []
        for p in model_copy.param_names:
            bounds = model_copy.bounds[p]
            try:
                diff = np.diff(bounds)[0]
            except TypeError:
                pass
            else:
                if diff > 0:
                    ranges.append(slice(*(bounds+(min(0.5*sigma, 0.1*diff),))))
                    continue
            ranges.append((getattr(model_copy, p).value,) * 2)

        # Ns=1 limits the fitting along an axis where the range is not a slice
        # object: this is those were the bounds are equal (i.e. fixed param)
        fitted_params = self._opt_method(self.objective_function, ranges,
                                         farg, Ns=1, finish=None, **kwargs)
        _fitter_to_model_params(model_copy, fitted_params)
        return model_copy
Ejemplo n.º 4
0
    def __call__(self, model, in_coords, ref_coords, sigma=5.0, maxsig=4.0,
                 **kwargs):
        model_copy = _validate_model(model, ['bounds', 'fixed'])

        # Starting simplex step size is set to be 5% of parameter values
        # Need to ensure this is larger than the convergence tolerance
        # so move the initial values away from zero if necessary
        try:
            xtol = kwargs['options']['xtol']
        except KeyError:
            pass
        else:
            for p in model_copy.param_names:
                pval = getattr(model_copy, p).value
                if abs(pval) < 20*xtol and 'offset' in p:
                    getattr(model_copy, p).value = 20*xtol if pval == 0 \
                        else (np.sign(pval) * 20*xtol)

        tree = spatial.cKDTree(list(zip(*ref_coords)))
        # avoid _convert_input since tree can't be coerced to a float
        x, y = in_coords
        farg = (model_copy, x, y, sigma, maxsig, tree)
        p0, _ = _model_to_fit_params(model_copy)

        result = self._opt_method(self.objective_function, p0, farg,
                                  **kwargs)
        fitted_params = result['x']
        _fitter_to_model_params(model_copy, fitted_params)
        return model_copy
Ejemplo n.º 5
0
    def evaluate(self, pars, neg=False):

        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)

        mean_model = self.model(self.x)

        if self.m == 1:
            loglike = -np.sum(np.log(mean_model)) - \
                      np.sum(self.y/mean_model)

        else:
            loglike = -2.0*self.m*(np.sum(np.log(mean_model)) +
                               np.sum(self.y/mean_model) +
                               np.sum((2.0 / (2. * self.m) - 1.0) *
                                      np.log(self.y)))


        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 6
0
    def __call__(self,
                 model,
                 x,
                 y,
                 weights=None,
                 maxiter=DEFAULT_MAXITER,
                 epsilon=DEFAULT_EPS):
        if model.linear:
            raise ModelLinearityError(
                'Model is linear in parameters; '
                'non-linear fitting methods should not be used.')

        model_copy = model.copy()
        init_values, fit_param_indicies = _model_to_fit_params(model_copy)
        bounds = np.array(list(model.bounds.values()))[fit_param_indicies]

        minimizer_kwargs = {"method": "BFGS"}
        opt_res = optimize.basinhopping(
            lambda fps: self.objective_function(fps, model_copy, x, y, weights
                                                ),
            init_values,
            minimizer_kwargs=minimizer_kwargs,
            accept_test=lambda *args, **kwargs: self._bounds_check(
                *args, bounds=bounds, **kwargs),
            take_step=lambda *args, **kwargs: self._take_step(
                *args, bounds=bounds, **kwargs),
            callback=lambda x, f, acc: self._dynamic_step(x, f, acc))

        _fitter_to_model_params(model_copy, opt_res.x)

        return model_copy
Ejemplo n.º 7
0
    def _compute_mean_model(self, pars):
        # if no polynomial is used, initialize the mean
        # model as a row of zeros
        if self.model is not None:
            _fitter_to_model_params(self.model, pars[-self.npar:])
            mean_model = self.model(self.x)

        else:
            mean_model = np.ones_like(self.x)

        if self.n_gauss > 0:
            # else get the weights vector out of the
            # parameter vector and compute the polynomial

            # get the weights out of the parameter vector
            w = pars[:self.n_gauss]

            # compute polynomial mean model
            mean_model *= np.dot(self.pft, w)

        # if responses are given, apply them before
        # calculating the likelihood
        if self.apply_response:
            model_counts = self._apply_response(mean_model)
        else:
            model_counts = mean_model

        return model_counts
Ejemplo n.º 8
0
    def __call__(self,
                 model,
                 in_coords,
                 ref_coords,
                 sigma=5.0,
                 maxsig=4.0,
                 **kwargs):
        model_copy = _validate_model(model, ['bounds', 'fixed'])

        # Starting simplex step size is set to be 5% of parameter values
        # Need to ensure this is larger than the convergence tolerance
        # so move the initial values away from zero if necessary
        try:
            xtol = kwargs['options']['xtol']
        except KeyError:
            pass
        else:
            for p in model_copy.param_names:
                pval = getattr(model_copy, p).value
                if abs(pval) < 20 * xtol and 'offset' in p:
                    getattr(model_copy, p).value = 20*xtol if pval == 0 \
                        else (np.sign(pval) * 20*xtol)

        tree = spatial.cKDTree(list(zip(*ref_coords)))
        # avoid _convert_input since tree can't be coerced to a float
        x, y = in_coords
        farg = (model_copy, x, y, sigma, maxsig, tree)
        p0, _ = _model_to_fit_params(model_copy)

        result = self._opt_method(self.objective_function, p0, farg, **kwargs)
        fitted_params = result['x']
        _fitter_to_model_params(model_copy, fitted_params)
        return model_copy
Ejemplo n.º 9
0
    def __call__(self,
                 model,
                 in_coords,
                 ref_coords,
                 sigma=5.0,
                 maxsig=4.0,
                 landscape=None,
                 **kwargs):
        model_copy = _validate_model(model, ['bounds', 'fixed'])

        # Turn 1D arrays into tuples to allow iteration over axes
        try:
            iter(in_coords[0])
        except TypeError:
            in_coords = (in_coords, )
        try:
            iter(ref_coords[0])
        except TypeError:
            ref_coords = (ref_coords, )

        # Remember, coords are x-first (reversed python order)
        if landscape is None:
            landshape = tuple(
                int(max(np.max(inco), np.max(refco)) + 10)
                for inco, refco in zip(in_coords, ref_coords))[::-1]
            landscape = self.mklandscape(ref_coords, sigma, maxsig, landshape)

        farg = (model_copy, np.asanyarray(in_coords, dtype=float), landscape)
        p0, _ = _model_to_fit_params(model_copy)

        # TODO: Use the name of the parameter to infer the step size
        ranges = []
        for p in model_copy.param_names:
            bounds = model_copy.bounds[p]
            try:
                diff = np.diff(bounds)[0]
            except TypeError:
                pass
            else:
                # We don't check that the value of a fixed param is within bounds
                if diff > 0 and not model_copy.fixed[p]:
                    ranges.append(
                        slice(*(bounds + (min(0.5 * sigma, 0.1 * diff), ))))
                    continue
            ranges.append((getattr(model_copy, p).value, ) * 2)

        # Ns=1 limits the fitting along an axis where the range is not a slice
        # object: this is those were the bounds are equal (i.e. fixed param)
        fitted_params = self._opt_method(self.objective_function,
                                         ranges,
                                         farg,
                                         Ns=1,
                                         finish=None,
                                         **kwargs)
        _fitter_to_model_params(model_copy, fitted_params)
        return model_copy
Ejemplo n.º 10
0
    def test_generate_model_data(self):
        pe = PSDParEst(self.ps)

        m = self.model
        _fitter_to_model_params(m, self.t0)

        model = m(self.ps.freq)

        pe_model = pe._generate_model(self.lpost, [2.0, 0.1, 100, 2.0])

        assert np.allclose(model, pe_model)
Ejemplo n.º 11
0
def lnprob(mc_params, model, bounds, measured_raw_cts, measured_bkg_cts, t_raw, t_bkg, x):
    min_bounds, max_bounds = bounds
    for value, min_bound, max_bound in zip(mc_params, min_bounds, max_bounds):
        if not np.isnan(min_bound) and value < min_bound:
            return -np.inf
        if not np.isnan(max_bound) and value > max_bound:
            return -np.inf

    _fitter_to_model_params(model, mc_params)
    lnp = 0. # TODO: evaluate prior based on bounds
    lnc = cstat(measured_raw_cts, model, measured_bkg_cts, t_raw, t_bkg, x)
    return lnp - lnc
Ejemplo n.º 12
0
    def evaluate(self, pars):

        # Fix values of fixed parameters
        print 'Antes...', pars
        pars = PrepareParameters(GlobalModel, pars)
        print 'Despues...', pars

        _fitter_to_model_params(GlobalModel, pars)
        mean_model = GlobalModel(self.x)
        loglike = np.sum(-0.5 * np.log(2. * np.pi) - np.log(self.yerr) -
                         (self.y - mean_model)**2 / (2. * self.yerr**2))
        return loglike
Ejemplo n.º 13
0
    def evaluate(self, pars, neg=False):
        """
        Evaluate the log-likelihood for a given set of parameters.

        Parameters
        ----------
        pars : numpy.ndarray
            An array of parameters at which to evaluate the model
            and subsequently the log-likelihood. Note that the
            length of this array must match the free parameters in
            ``model``, i.e. ``npar``

        neg : bool, optional, default ``False``
            If ``True``, return the *negative* log-likelihood, i.e.
            ``-loglike``, rather than ``loglike``. This is useful e.g.
            for optimization routines, which generally minimize
            functions.

        Returns
        -------
        loglike : float
            The log(likelihood) value for the data and model.

        """
        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)


        mean_model = self.model(self.x)

        with warnings.catch_warnings(record=True) as out:

            if self.m == 1:
                loglike = -np.sum(np.log(mean_model)) - \
                          np.sum(self.y/mean_model)

            else:

                    loglike = -2.0*self.m*(np.sum(np.log(mean_model)) +
                                       np.sum(self.y/mean_model) +
                                       np.sum((2.0 / (2. * self.m) - 1.0) *
                                              np.log(self.y)))

        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 14
0
    def test_compute_model(self):

        self.optres._compute_model(self.lpost)

        assert hasattr(self.optres,
                       "mfit"), "OptimizationResult object should have mfit " \
                                "attribute at this point!"

        _fitter_to_model_params(self.model, self.opt.x)
        mfit_test = self.model(self.lpost.x)

        assert np.allclose(self.optres.mfit, mfit_test)
Ejemplo n.º 15
0
    def evaluate(self, params):
        # Daniela: set the input parameters in the astropy model using the
        # list of parameters in params
        _fitter_to_model_params(self.model, params)

        # Daniela: make the mean model
        mean_model = self.model(x)

        # Daniela: not sure what your 'x' in this log-likelihood is, but it should be
        # the mean model
        loglike = np.sum(-mean_model + self.y*np.log(mean_model) - gammaln(self.y + 1))

        return loglike
Ejemplo n.º 16
0
def lnprob(mc_params, model, bounds, measured_raw_cts, measured_bkg_cts, t_raw,
           t_bkg, x):
    min_bounds, max_bounds = bounds
    for value, min_bound, max_bound in zip(mc_params, min_bounds, max_bounds):
        if not np.isnan(min_bound) and value < min_bound:
            return -np.inf
        if not np.isnan(max_bound) and value > max_bound:
            return -np.inf

    _fitter_to_model_params(model, mc_params)
    lnp = 0.  # TODO: evaluate prior based on bounds
    lnc = cstat(measured_raw_cts, model, measured_bkg_cts, t_raw, t_bkg, x)
    return lnp - lnc
Ejemplo n.º 17
0
    def test_generate_model_data(self):
        pe = PSDParEst(self.ps)

        m = self.model
        _fitter_to_model_params(m, self.t0)

        model = m(self.ps.freq)

        pe_model = pe._generate_model(self.lpost, [self.x_0_0, self.fwhm_0,
                                                   self.amplitude_0,
                                                   self.amplitude_1])

        assert np.allclose(model, pe_model)
Ejemplo n.º 18
0
    def evaluate(self, pars, neg=False):
        """
        Evaluate the log-likelihood for a given set of parameters.

        Parameters
        ----------
        pars : numpy.ndarray
            An array of parameters at which to evaluate the model
            and subsequently the log-likelihood. Note that the
            length of this array must match the free parameters in
            ``model``, i.e. ``npar``

        neg : bool, optional, default ``False``
            If ``True``, return the *negative* log-likelihood, i.e.
            ``-loglike``, rather than ``loglike``. This is useful e.g.
            for optimization routines, which generally minimize
            functions.

        Returns
        -------
        loglike : float
            The log(likelihood) value for the data and model.

        """
        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)

        mean_model = self.model(self.x)

        with warnings.catch_warnings(record=True) as out:

            if self.m == 1:
                loglike = -np.sum(np.log(mean_model)) - \
                          np.sum(self.y/mean_model)

            else:

                loglike = -2.0 * self.m * (np.sum(np.log(mean_model)) + np.sum(
                    self.y / mean_model) + np.sum(
                        (2.0 / (2. * self.m) - 1.0) * np.log(self.y)))

        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 19
0
    def test_compute_model(self):
        optres = OptimizationResultsSubclassDummy(self.lpost, self.opt,
                                                  neg=True)

        optres._compute_model(self.lpost)

        assert hasattr(optres,
                       "mfit"), "OptimizationResult object should have mfit " \
                                "attribute at this point!"

        _fitter_to_model_params(self.model, self.opt.x)
        mfit_test = self.model(self.lpost.x)

        assert np.all(optres.mfit == mfit_test)
Ejemplo n.º 20
0
def lnlike(theta, x, y, yerr, model):
    # Convert the array of parameter values back into model parameters
    _fitter_to_model_params(model, theta)

    mod_y = model(x)

    # inv_sigma2 = 1.0 / (yerr ** 2 + mod_y ** 2 * np.exp(2 * lnf))
    # res = -0.5 * (np.sum((y - mod_y) ** 2 * inv_sigma2 - np.log(inv_sigma2)))
    if np.sum(yerr) > 0:
        res = -0.5 * np.sum(((y - mod_y) / yerr)**2)
    else:
        res = -0.5 * np.sum((y - mod_y)**2)

    return res
Ejemplo n.º 21
0
    def __call__(self,
                 model,
                 *args,
                 weights=None,
                 maxiter=100,
                 acc=1e-7,
                 epsilon=1.4901161193847656e-08,
                 estimate_jacobian=False):
        from scipy import optimize

        model_copy = _validate_model(model, self.supported_constraints)
        farg = (
            model_copy,
            weights,
        ) + args
        if model_copy.fit_deriv is None or estimate_jacobian:
            dfunc = None
        else:
            dfunc = self._wrap_deriv
        init_values, _ = _model_to_fit_params(model_copy)
        fitparams, cov_x, dinfo, mess, ierr = optimize.leastsq(
            self.objective_function,
            init_values,
            args=farg,
            Dfun=dfunc,
            col_deriv=model_copy.col_fit_deriv,
            maxfev=maxiter,
            epsfcn=epsilon,
            xtol=acc,
            full_output=True)
        _fitter_to_model_params(model_copy, fitparams)
        self.fit_info.update(dinfo)
        self.fit_info['cov_x'] = cov_x
        self.fit_info['message'] = mess
        self.fit_info['ierr'] = ierr
        if ierr not in [1, 2, 3, 4]:
            warnings.warn(
                "The fit may be unsuccessful; check "
                "fit_info['message'] for more information.",
                AstropyUserWarning)

        # now try to compute the true covariance matrix
        if (len(args[-1]) > len(init_values)) and cov_x is not None:
            sum_sqrs = np.sum(self.objective_function(fitparams, *farg)**2)
            dof = len(args[-1]) - len(init_values)
            self.fit_info['param_cov'] = cov_x * sum_sqrs / dof
        else:
            self.fit_info['param_cov'] = None

        return model_copy
Ejemplo n.º 22
0
def create_simulated_power_spectra(nx, ny, observation_model, model_parameters, frequencies):
    d = np.zeros([nx, ny, len(frequencies)])
    for i in range(0, nx):
        this_alpha = model_parameters[1][i]
        for j in range(0, ny):
            # This section will be replaced with a section that reads observed power spectra
            # Set the model parameters
            _fitter_to_model_params(observation_model,
                                    [model_parameters[0], this_alpha, model_parameters[2]])
            # Create the true data
            psd_shape = observation_model(frequencies)

            # Now randomize the true data and store it in an iterable
            d[i, j, :] = psd_shape * np.random.chisquare(2, size=psd_shape.shape[0]) / 2.0
    return d
Ejemplo n.º 23
0
    def __call__(self, model, x, y, weights=None, **kwargs):
        """
        Fit data to this model.

        Parameters
        ----------
        model : `~astropy.modeling.FittableModel`
            model to fit to x, y
        x : array
            input coordinates
        y : array
            input coordinates
        weights : array, optional
            Weights for fitting.
            For data with Gaussian uncertainties, the weights should be
            1/sigma.
        kwargs : dict
            optional keyword arguments to be passed to the optimizer or the statistic

        Returns
        -------
        model_copy : `~astropy.modeling.FittableModel`
            a copy of the input model with parameters set by the fitter
        """

        model_copy = _validate_model(model,
                                     self._opt_method.supported_constraints)
        farg = _convert_input(x, y)
        farg = (model_copy, weights) + farg
        p0, _ = _model_to_fit_params(model_copy)

        fitparams, self.fit_info = self._opt_method(
            self.log_probability,
            p0,
            farg,
            self.nsteps,
            save_samples=self.save_samples,
            **kwargs)

        # set the output model parameters to the "best fit" parameters
        _fitter_to_model_params(model_copy, fitparams)

        # get and set the symmetric and asymmetric uncertainties on each parameter
        model_copy = self._set_uncs_and_posterior(model_copy)

        return model_copy
Ejemplo n.º 24
0
    def _compute_mean_model(self, pars):
        # if no polynomial is used, initialize the mean
        # model as a row of zeros
        if self.bkg_model is not None:
            # background model parameters are the second-to-last few in the list:
            if self.src_model is not None:
                bkg_pars = pars[-self.bkg_npar - self.src_npar:-self.src_npar]
            else:
                bkg_pars = pars[-self.bkg_npar - self.src_npar:]
            _fitter_to_model_params(self.bkg_model, bkg_pars)
            mean_model = self.bkg_model(self.x)

        else:
            mean_model = np.ones_like(self.x)

        if self.n_gauss > 0:
            # else get the weights vector out of the
            # parameter vector and compute the polynomial

            # get the weights out of the parameter vector
            w = pars[:self.n_gauss]

            # compute polynomial mean model
            mean_model *= np.dot(self.pft, w)

        if self.src_model is not None:
            # background model parameters are the second-to-last few in the list:
            src_pars = pars[-self.src_npar:]
            _fitter_to_model_params(self.src_model, src_pars)
            source_model = self.src_model(self.x) + mean_model

        else:
            source_model = None

        # if responses are given, apply them before
        # calculating the likelihood
        if self.apply_response:
            bkg_counts, source_counts = self._apply_response(
                mean_model, source_model)
        else:
            bkg_counts = mean_model
            source_counts = source_model

        return bkg_counts, source_counts
Ejemplo n.º 25
0
    def evaluate(self, pars, neg=False):
        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)

        mean_model = self.model(self.x)

        loglike = np.sum(-0.5*np.log(2.*np.pi) - np.log(self.yerr) -
                         (self.y-mean_model)**2/(2.*self.yerr**2))

        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 26
0
    def __call__(self,
                 model,
                 in_coords,
                 ref_coords,
                 sigma=5.0,
                 maxsig=4.0,
                 **kwargs):
        model_copy = _validate_model(model, ['bounds'])
        x, y = in_coords
        xref, yref = ref_coords
        xmax = max(np.max(x), np.max(xref))
        ymax = max(np.max(y), np.max(yref))
        landscape = self.mklandscape(ref_coords, sigma, maxsig,
                                     (int(ymax), int(xmax)))
        farg = (model_copy, ) + _convert_input(x, y, landscape)
        p0, _ = _model_to_fit_params(model_copy)

        # TODO: Use the name of the parameter to infer the step size
        ranges = []
        for p in model_copy.param_names:
            bounds = model_copy.bounds[p]
            try:
                diff = np.diff(bounds)[0]
            except TypeError:
                pass
            else:
                if diff > 0:
                    ranges.append(
                        slice(*(bounds + (min(0.5 * sigma, 0.1 * diff), ))))
                    continue
            ranges.append((getattr(model_copy, p).value, ) * 2)

        # Ns=1 limits the fitting along an axis where the range is not a slice
        # object: this is those were the bounds are equal (i.e. fixed param)
        fitted_params = self._opt_method(self.objective_function,
                                         ranges,
                                         farg,
                                         Ns=1,
                                         finish=None,
                                         **kwargs)
        _fitter_to_model_params(model_copy, fitted_params)
        return model_copy
Ejemplo n.º 27
0
    def evaluate(self, pars, neg=False):
        """
        Evaluate the Gaussian log-likelihood for a given set of parameters.

        Parameters
        ----------
        pars : numpy.ndarray
            An array of parameters at which to evaluate the model
            and subsequently the log-likelihood. Note that the
            length of this array must match the free parameters in
            ``model``, i.e. ``npar``

        neg : bool, optional, default ``False``
            If ``True``, return the *negative* log-likelihood, i.e.
            ``-loglike``, rather than ``loglike``. This is useful e.g.
            for optimization routines, which generally minimize
            functions.

        Returns
        -------
        loglike : float
            The log(likelihood) value for the data and model.

        """
        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)

        mean_model = self.model(self.x)

        loglike = np.sum(-0.5*np.log(2.*np.pi) - np.log(self.yerr) -
                         (self.y-mean_model)**2/(2.*self.yerr**2))

        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 28
0
    def evaluate(self, pars, neg=False):
        """
        Evaluate the Gaussian log-likelihood for a given set of parameters.

        Parameters
        ----------
        pars : numpy.ndarray
            An array of parameters at which to evaluate the model
            and subsequently the log-likelihood. Note that the
            length of this array must match the free parameters in
            ``model``, i.e. ``npar``

        neg : bool, optional, default ``False``
            If ``True``, return the *negative* log-likelihood, i.e.
            ``-loglike``, rather than ``loglike``. This is useful e.g.
            for optimization routines, which generally minimize
            functions.

        Returns
        -------
        loglike : float
            The log(likelihood) value for the data and model.

        """
        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)

        mean_model = self.model(self.x)

        loglike = np.sum(-0.5 * np.log(2. * np.pi) - np.log(self.yerr) -
                         (self.y - mean_model)**2 / (2. * self.yerr**2))

        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 29
0
    def __call__(self, model, x, measured_raw_cts, measured_bkg_cts,
                 t_raw, t_bkg, x_err=None, **kwargs):
        if x_err is not None:
            model = IntModel(model.__class__)(x_err, *model.parameters)

        model_copy = _validate_model(model,
                                     self.supported_constraints)
        farg = _convert_input(x, measured_raw_cts)
        farg = (model_copy, measured_bkg_cts, t_raw, t_bkg) + farg
        p0, _ = _model_to_fit_params(model_copy)

        # TODO: Honor estimate_jacobian in kwargs, and/or determine if
        # model supports jacobian, and/or if fitter supports the jac argument.

        fitparams, self.fit_info = self._opt_method(
            self.objective_function, p0, farg, jac=self.objective_derivative,
            **kwargs)
        _fitter_to_model_params(model_copy, fitparams)

        return model_copy
Ejemplo n.º 30
0
    def evaluate(self, pars, neg=False):

        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)

        mean_model = self.model(self.x)

        loglike = np.sum(-mean_model + self.y*np.log(mean_model) \
               - scipy_gammaln(self.y + 1.))

        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 31
0
    def Minimize_OutputAnalysis(self, output):

        popt, pcov = output
        nparam = len(GlobalModel.parameters)
        _fitter_to_model_params(GlobalModel, popt)
        mean_model = GlobalModel(self.r)
        errors = np.sqrt(np.diag(pcov))
        chi2 = Chi2Reduced(mean_model, self.shear, self.shear_err, df=nparam)

        more = {
            'model_name': GlobalModel.name,
            'param_names':
            [n.encode('utf-8') for n in GlobalModel.param_names],
            'param_values': popt,
            'param_errors': errors,
            'param_covar': pcov,
            'chi2': chi2
        }
        output = scipy.optimize.optimize.OptimizeResult(more)
        return output
Ejemplo n.º 32
0
    def objective_function(self, fps, *args):
        """
        Function to minimize.

        Parameters
        ----------
        fps : list
            parameters returned by the fitter
        args : list
            [model, [weights], [input coordinates]]
        """

        model = args[0]
        weights = args[1]
        fitting._fitter_to_model_params(model, fps)
        meas = args[-1]
        if weights is None:
            return np.ravel(np.log(model(*args[2 : -1])) - np.log(meas))
        else:
            return np.ravel(np.log(weights * model(*args[2 : -1])) - np.log(weights * meas))
Ejemplo n.º 33
0
    def evaluate(self, pars, neg=False):

        if np.size(pars) != self.npar:
            raise IncorrectParameterError("Input parameters must" +
                                          " match model parameters!")

        _fitter_to_model_params(self.model, pars)

        mean_model = self.model(self.x)

        with warnings.catch_warnings(record=True) as out:

            loglike = np.sum(-np.log(2.*self.yerr) - \
                      (np.abs(self.y - mean_model)/self.yerr))

        if not np.isfinite(loglike):
            loglike = logmin

        if neg:
            return -loglike
        else:
            return loglike
Ejemplo n.º 34
0
    def _generate_model(self, lpost, pars):
        """
        Helper function that generates a fake PSD similar to the
        one in the data, but with different parameters.

        Parameters
        ----------
        lpost : instance of a Posterior or LogLikelihood subclass
            The object containing the relevant information about the
            data and the model

        pars : iterable
            A list of parameters to be passed to lpost.model in oder
            to generate a model data set.

        Returns:
        --------
        model_data : numpy.ndarray
            An array of model values for each bin in lpost.x

        """

        assert isinstance(lpost, LogLikelihood) or isinstance(lpost, Posterior), \
            "lpost must be of type LogLikelihood or Posterior or one of its " \
            "subclasses!"

        # assert pars is of correct length
        assert len(pars) == lpost.npar, "pars must be a list " \
                                        "of %i parameters"%lpost.npar
        # get the model
        m = lpost.model

        # reset the parameters
        _fitter_to_model_params(m, pars)

        # make a model spectrum
        model_data = lpost.model(lpost.x)

        return model_data
Ejemplo n.º 35
0
            # Daniela: for maximum likelihood fitting, we need to define the *negative*
            # log-likelihood:
            neg_loglike_sing = lambda x: -loglike_sing(x)

            # Daniela: here's the optimization:
            opt_sing = minimize(neg_loglike_sing, init_params_s,
                                method="L-BFGS-B", tol=1.e-10)

            # Daniela: print the negative log-likelihood:
            #print("The value of the negative log-likelihood: " + str(opt_sing.fun))

            # Daniela: the parameters at the maximum of the likelihood is in opt.x:
            fit_pars = opt_sing.x

            # Daniela : now we can put the parameters back into the Gaussian model
            _fitter_to_model_params(gaus_sing, fit_pars)


            # Bayesian information criterion
            # see also: https://en.wikipedia.org/wiki/Bayesian_information_criterion
            # bic = -2*loglike + n_params * log(n_datapoints)
            # note to myself: opt.fun is -loglike, so we'll just use that here
            bic_sing = 2.*opt_sing.fun + fit_pars.shape[0]*np.log(x.shape[0])

            # Daniela: from here on, you can do the same for the model with two Gaussians
            # Then you can compare the two BICs for a slightly hacky way of model
            # comparison


            # DOUBLE GAUSSIAN FITTING
            ydg = y[:]
Ejemplo n.º 36
0
    def _compute_model(self, lpost):

        _fitter_to_model_params(lpost.model, self.p_opt)

        self.mfit = lpost.model(lpost.x)
Ejemplo n.º 37
0
# fix x_0 of power law component
pl.x_0.fixed = True

# define constant
c = models.Const1D()

# make compound model
plc = pl + c

# parameters for fake data.
alpha = 2.0
amplitude = 5.0
white_noise = 2.0
freq = np.linspace(0.01, 10.0, int(10.0 / 0.01))
from astropy.modeling.fitting import _fitter_to_model_params
_fitter_to_model_params(plc, [amplitude, alpha, white_noise])
psd_shape = plc(freq)
powers = psd_shape * np.random.chisquare(2, size=psd_shape.shape[0]) / 2.0

ps = Powerspectrum()
ps.freq = freq
ps.power = powers
ps.df = ps.freq[1] - ps.freq[0]
ps.m = 1
loglike = PSDLogLikelihood(ps.freq, ps.power, plc, m=ps.m)
test_pars = [1, 5, 100]
parest = PSDParEst(ps, fitmethod="L-BFGS-B", max_post=True)

# flat prior for the power law index
p_alpha = lambda alpha: ((-1. <= alpha) & (alpha <= 5.))
Ejemplo n.º 38
0
    def __call__(self,
                 model,
                 in_coords,
                 ref_coords,
                 in_weights=None,
                 ref_weights=None,
                 matches=None,
                 **kwargs):
        """
        Perform a minimization using the KDTreeFitter

        Parameters
        ----------
        model: FittableModel
            initial guess at model defining transformation
        in_coords: array-like (n x N)
            array of input coordinates
        ref_coords: array-like (n x M)
            array of reference coordinates
        in_weights: array-like (N,)
            weights for input coordinates
        ref_weights: array-like (M,)
            weights for reference coordinates
        kwargs: dict
            additional arguments to control fit

        Returns
        -------
        Model: best-fitting model
        also assigns attributes:
        x: array-like
            best-fitting parameters
        fun: float
            final value of fitting function
        nit: int
            number of iterations performed
        """
        model_copy = _validate_model(model, ['bounds', 'fixed'])

        # Turn 1D arrays into tuples to allow iteration over axes
        try:
            iter(in_coords[0])
        except TypeError:
            in_coords = (in_coords, )
        try:
            iter(ref_coords[0])
        except TypeError:
            ref_coords = (ref_coords, )

        # Starting simplex step size is set to be 5% of parameter values
        # Need to ensure this is larger than the convergence tolerance
        # so move the initial values away from zero if necessary
        try:
            xatol = kwargs['options']['xatol']
        except KeyError:
            pass
        else:
            for p in model_copy.param_names:
                pval = getattr(model_copy, p).value
                ### EDITED THIS LINE SO TAKE A LOOK IF 2D MATCHING GOES WRONG!!
                if abs(pval) < 20 * xatol and not model_copy.fixed[
                        p]:  # and 'offset' in p
                    getattr(model_copy, p).value = 20 * xatol if pval == 0 \
                        else (np.sign(pval) * 20 * xatol)

        if in_weights is None:
            in_weights = np.ones((len(in_coords[0]), ))
        if ref_weights is None:
            ref_weights = np.ones((len(ref_coords[0]), ))
        # cKDTree.query() returns a value of n for no neighbour so make coding
        # easier by allowing this to match a zero-weighted reference
        ref_weights = np.append(ref_weights, (0, ))

        ref_coords = np.array(list(zip(*ref_coords)))
        tree = spatial.cKDTree(ref_coords)
        # avoid _convert_input since tree can't be coerced to a float
        farg = (model_copy, in_coords, ref_coords, in_weights, ref_weights,
                matches, tree)
        p0, _ = _model_to_fit_params(model_copy)

        arg_names = inspect.getfullargspec(self._opt_method).args
        args = [self.objective_function]
        if arg_names[1] == 'x0':
            args.append(p0)
        elif arg_names[1] == 'bounds':
            args.append(
                tuple(model_copy.bounds[p] for p in model_copy.param_names))
        else:
            raise ValueError("Don't understand argument {}".format(
                arg_names[1]))

        if 'args' in arg_names:
            kwargs['args'] = farg

        if 'method' in arg_names:
            kwargs['method'] = self._method

        if 'minimizer_kwargs' in arg_names:
            kwargs['minimizer_kwargs'] = {
                'args': farg,
                'method': 'Nelder-Mead'
            }

        result = self._opt_method(*args, **kwargs)

        fitted_params = result['x']
        _fitter_to_model_params(model_copy, fitted_params)
        self.statistic = result['fun']
        self.niter = result['nit']
        return model_copy
Ejemplo n.º 39
0
 def objective_derivative(self, params, model, measured_bkg_cts, t_raw, t_bkg, x, measured_raw_cts):
     _fitter_to_model_params(model, params)
     return cstat_deriv(measured_raw_cts, model, measured_bkg_cts,
                        t_raw, t_bkg, x)
Ejemplo n.º 40
0
    # subplot
    ax2 = plt.axes([0.60, 0.35, 0.35, 0.35])

    # plot the bands and all spectra for this star
    extdata.plot(ax, color="k", alpha=0.5)
    extdata.plot(ax2, color="k", alpha=0.5)

    # plot samples from the mcmc chaing
    flat_samples = fit2.fit_info["sampler"].get_chain(discard=int(0.1 *
                                                                  nsteps),
                                                      flat=True)
    inds = np.random.randint(len(flat_samples), size=100)
    model_copy = p92_fit2.copy()
    for ind in inds:
        sample = flat_samples[ind]
        _fitter_to_model_params(model_copy, sample)
        ax.plot(1.0 / x, model_copy(x), "C1", alpha=0.05)
        ax2.plot(1.0 / x, model_copy(x), "C1", alpha=0.05)
    # for the figure legend
    ax.plot(1.0 / x, model_copy(x), "C1", alpha=0.05, label="EMCEE Fits")
    ax2.plot(1.0 / x, model_copy(x), "C1", alpha=0.05, label="EMCEE Fits")

    # ax.plot(1.0 / x, p92_init(x), "r--", label="P92 Init")
    ax.plot(1.0 / x, p92_fit(x), "r-", label="P92 Best Fit")
    ax2.plot(1.0 / x, p92_fit(x), "r-")

    # show components of best fitter
    p92_comps = p92_fit.copy()
    p92_comps.FUV_amp_0 = 0.0
    p92_comps.NUV_amp_0 = 0.0
    p92_comps.SIL1_amp_0 = 0.0