Exemplo n.º 1
0
 def _start_sampling(self):
     nestle.sample(loglikelihood=self._calc_function,
                   prior_transform=self._loaded_function,
                   ndim=self._ndim,
                   npoints=self._npoints,
                   method=self._method,
                   update_interval=self._update_interval,
                   npdim=self._npdim,
                   maxiter=self._maxiter,
                   maxcall=self._maxcall,
                   dlogz=self._dlogz,
                   decline_factor=self._decline_factor)
Exemplo n.º 2
0
def run_flat(method):
    logl = lambda x: 0.0
    prior = lambda x: x
    res = nestle.sample(logl, prior, 2, method=method,
                        npoints=4, rstate=RandomState(0))
    assert_allclose(res.logz, 0.0, atol=1.e-10)
    assert_allclose(res.h, 0.0, atol=1.e-10)
Exemplo n.º 3
0
def nestle_multi2():
    # Run nested sampling
    res = nestle.sample(loglike2,
                        prior_transform2,
                        3,
                        method='multi',
                        npoints=2000)
    print(res.summary())

    # weighted average and covariance:
    pm, covm = nestle.mean_and_cov(res.samples, res.weights)

    # re-scale weights to have a maximum of one
    nweights = res.weights / np.max(res.weights)

    # get the probability of keeping a sample from the weights
    keepidx = np.where(np.random.rand(len(nweights)) < nweights)[0]

    # get the posterior samples
    samples_nestle = res.samples[keepidx, :]

    print(np.mean(samples_nestle[:, 0]))  # mean of A samples
    print(np.std(samples_nestle[:, 0]))  # standard deviation of A samples
    print(np.mean(samples_nestle[:, 1]))  # mean of w samples
    print(np.std(samples_nestle[:, 1]))  # standard deviation of w samples
    print(np.mean(samples_nestle[:, 2]))  # mean of t0 samples
    print(np.std(samples_nestle[:, 2]))  # standard deviation of t0 samples
    print(len(samples_nestle))  # number of posterior samples

    return res.logz
Exemplo n.º 4
0
    def run_sampler(self):
        """ Runs Nestle sampler with given kwargs and returns the result

        Returns
        =======
        bilby.core.result.Result: Packaged information about the result

        """
        import nestle
        out = nestle.sample(
            loglikelihood=self.log_likelihood,
            prior_transform=self.prior_transform,
            ndim=self.ndim, **self.kwargs)
        print("")

        self.result.sampler_output = out
        self.result.samples = nestle.resample_equal(out.samples, out.weights)
        self.result.nested_samples = DataFrame(
            out.samples, columns=self.search_parameter_keys)
        self.result.nested_samples['weights'] = out.weights
        self.result.nested_samples['log_likelihood'] = out.logl
        self.result.log_likelihood_evaluations = self.reorder_loglikelihoods(
            unsorted_loglikelihoods=out.logl, unsorted_samples=out.samples,
            sorted_samples=self.result.samples)
        self.result.log_evidence = out.logz
        self.result.log_evidence_err = out.logzerr
        self.result.information_gain = out.h
        self.calc_likelihood_count()
        return self.result
Exemplo n.º 5
0
def run_two_gaussians(method):
    sigma = 0.1
    mu1 = np.ones(2)
    mu2 = -np.ones(2)
    sigma_inv = np.identity(2) / 0.1**2

    def logl(x):
        dx1 = x - mu1
        dx2 = x - mu2
        return np.logaddexp(-np.dot(dx1, np.dot(sigma_inv, dx1)) / 2.0,
                            -np.dot(dx2, np.dot(sigma_inv, dx2)) / 2.0)

    # Flat prior, over [-5, 5] in both dimensions
    def prior(x):
        return 10.0 * x - 5.0

    #(Approximate) analytic evidence for two identical Gaussian blobs,
    # over a uniform prior [-5:5][-5:5] with density 1/100 in this domain:
    analytic_logz = np.log(2.0 * 2.0*np.pi*sigma*sigma / 100.)
    grid_logz = integrate_on_grid_refine(logl, [(-5., 5.), (-5., 5.)])

    res = nestle.sample(logl, prior, 2, method=method,
                        npoints=100, rstate=RandomState(0))
    print()
    print("{}: logz           = {:6.3f} +/- {:6.3f}"
          .format(method, res.logz, res.logzerr))
    print("        grid_logz      = {0:8.5f}".format(grid_logz))
    print("        analytic_logz  = {0:8.5f}".format(analytic_logz))
    assert abs(res.logz - grid_logz) < 3.0 * res.logzerr
    assert abs(res.weights.sum() - 1.) < SQRTEPS
Exemplo n.º 6
0
def test_eggbox():
    tmax = 5.0 * np.pi
    constant = np.log(1.0 / tmax**2)

    def loglike(x):
        t = 2.0 * tmax * x - tmax
        return (2.0 + np.cos(t[0] / 2.0) * np.cos(t[1] / 2.0))**5.0

    def prior(x):
        return x

    res = nestle.sample(loglike,
                        prior,
                        2,
                        npoints=500,
                        method='multi',
                        rstate=RandomState(0))

    grid_logz = integrate_on_grid_refine(loglike, [(0., 1.), (0., 1.)])

    print("\nEggbox")
    print("multi : logz           = {:6.3f} +/- {:6.3f}".format(
        res.logz, res.logzerr))
    print("        grid_logz      = {0:8.5f}".format(grid_logz))

    assert abs(res.logz - grid_logz) < 3.0 * res.logzerr
Exemplo n.º 7
0
def run_two_gaussians(method):
    sigma = 0.1
    mu1 = np.ones(2)
    mu2 = -np.ones(2)
    sigma_inv = np.identity(2) / 0.1**2

    def logl(x):
        dx1 = x - mu1
        dx2 = x - mu2
        return np.logaddexp(-np.dot(dx1, np.dot(sigma_inv, dx1)) / 2.0,
                            -np.dot(dx2, np.dot(sigma_inv, dx2)) / 2.0)

    # Flat prior, over [-5, 5] in both dimensions
    def prior(x):
        return 10.0 * x - 5.0

    #(Approximate) analytic evidence for two identical Gaussian blobs,
    # over a uniform prior [-5:5][-5:5] with density 1/100 in this domain:
    analytic_logz = np.log(2.0 * 2.0 * np.pi * sigma * sigma / 100.)
    grid_logz = integrate_on_grid_refine(logl, [(-5., 5.), (-5., 5.)])

    res = nestle.sample(logl,
                        prior,
                        2,
                        method=method,
                        npoints=100,
                        rstate=RandomState(0))
    print()
    print("{}: logz           = {:6.3f} +/- {:6.3f}".format(
        method, res.logz, res.logzerr))
    print("        grid_logz      = {0:8.5f}".format(grid_logz))
    print("        analytic_logz  = {0:8.5f}".format(analytic_logz))
    assert abs(res.logz - grid_logz) < 3.0 * res.logzerr
Exemplo n.º 8
0
    def nested(self, sigma):
        """
        @returns Nested sampling integration of shape parameters
        """
        def loglike(shape):
            """
            @returns Log-likelihood
            """
            self.set_velocity_dist(MB(*shape))
            return self.treatment.loglike(sigma)

        def prior(x):
            """
            @returns Shape parameters sampled from Gaussians
            """
            return (norm.ppf(x[0],
                             *self.V_MODE), norm.ppf(x[1], *self.V_ESCAPE))

        result = nestle.sample(loglike,
                               prior,
                               2,
                               maxcall=1000,
                               dlogz=0.5,
                               npoints=25)
        return result
Exemplo n.º 9
0
def run_sampler(model, prior_transform, data, z=0.306, npts=100):

    print model.description()

    data_x, data_y, data_yerr = data

    Likelihood = model.Likelihood
    loglike = Likelihood(data_x, data_y, data_yerr, z)

    ndim = model.N_PARAMS

    begin_time = time()
    result = nestle.sample(loglike,
                           prior_transform,
                           ndim,
                           npoints=npts,
                           method='multi',
                           callback=nestle.print_progress)
    end_time = time()
    run_time = end_time - begin_time
    print "Time elapsed = ", run_time
    print "Time per likelihood call = ", run_time / result.ncall

    print "log z = ", result.logz  # log evidence
    print "log z err = ", result.logzerr  # numerical (sampling) error on logz

    return result
Exemplo n.º 10
0
def run_nestle_sampler(lnprobfn, model, verbose=True, callback=None,
                       nestle_method='single', nestle_npoints=200,
                       nestle_maxcall=int(1e6), **kwargs):


    result = nestle.sample(lnprobfn, model.prior_transform, model.ndim,
                           method=nestle_method, npoints=nestle_npoints,
                           callback=nestle.print_progress, maxcall=nestle_maxcall)
    return result
Exemplo n.º 11
0
def show_results(loglike_NFW, prior_transform_NFW, n):
    # n is the dim of theta; for NFW model, n =2
    result = nestle.sample(loglike_NFW, prior_transform_NFW, 2)

    print('log evidence')
    print(result.logz)

    print('numerical (sampling) error on logz')
    print(result.logzerr)

    print('array of sample parameters')
    print(result.samples)

    print('array of weights associated with each sample')
    print(result.weights)

    p, cov = nestle.mean_and_cov(result.samples, result.weights)

    print("core radius a = {0:5.2f} +/- {1:5.2f} kpc".format(
        p[0], np.sqrt(cov[0, 0])))
    print("normalization factor = {0:5.2f} +/- {1:5.2f}".format(
        p[1], np.sqrt(cov[1, 1])))
    print(
        "Halo density normalization constant = {0:5.2e} +/- {1:5.2e} Msun/kpc^3"
        .format(2.312E5 * p[1], 2.312E5 * np.sqrt(cov[1, 1])))

    # Note: in order to convert the model to units of Msun/kpc^3 we multiply its value by 2.312E5.
    # See comments in the model definition for details.
    print("Halo density in our solor system = {0:5.2e} Msun/kpc^3.".format(
        2.312E5 * model_NFW(p, 8)))

    # Note: 1 Msun/kpc^3 = 3.817E-2 (GeV/c^2)/m^3 = 3.817E-5 (GeV/c^2)/(dm^3)
    # 1 dm^3 = 1 liter.
    # 3 WIMPS/liter would be 300 GeV/c^2/liter
    print("Halo density in our solor system = {0:5.2e} GeV/c^2/liter.".format(
        3.817E-5 * 2.312E5 * model_NFW(p, 8)))

    plt.figure()
    plt.errorbar(data_x, data_y, data_yerr, data_xerr, fmt='*')
    plt.xlabel("r (kpc)")
    plt.ylabel('V (km/s)')
    plt.title(
        "The measured rotational speed of the interstellar medium as a fucntion of the galactocentric radius"
    )
    plt.plot([5., 200.], model_NFW(p, np.array([5., 200.])))
    plt.show()

    fig = corner.corner(result.samples,
                        weights=result.weights,
                        labels=['a', 'rho0'],
                        range=[0.99999, 0.99999],
                        bins=30)
    plt.show()

    return 0
Exemplo n.º 12
0
def run_nestle_sampler(lnprobfn, model, verbose=True,
                       callback=None,
                       nestle_method='multi', nestle_npoints=200,
                       nestle_maxcall=int(1e6), nestle_update_interval=None,
                       **kwargs):

    result = nestle.sample(lnprobfn, model.prior_transform, model.ndim,
                           method=nestle_method, npoints=nestle_npoints,
                           callback=callback, maxcall=nestle_maxcall,
                           update_interval=nestle_update_interval)
    return result
Exemplo n.º 13
0
def run(ndim):
    """Convenience function for running in any dimension"""

    c1 = np.zeros(ndim)
    c1[0] = -3.5
    c2 = np.zeros(ndim)
    c2[0] = 3.5
    f = lambda theta: loglike(theta, c1, c2)
    
    return nestle.sample(f, prior_transform, ndim, method='multi',
                         npoints=npoints, rstate=rstate)
Exemplo n.º 14
0
def run_flat(method):
    logl = lambda x: 0.0
    prior = lambda x: x
    res = nestle.sample(logl,
                        prior,
                        2,
                        method=method,
                        npoints=4,
                        rstate=RandomState(0))
    assert_allclose(res.logz, 0.0, atol=1.e-10)
    assert_allclose(res.h, 0.0, atol=1.e-10)
Exemplo n.º 15
0
 def run_nestle(self,outfile='TEST.dat'):
     # initalize outfile 
     self.outfile = open(outfile,'w')
     self.outfile.write('ITER Teff Dist Rad NH arfsc1 arfsc2 log(z) \n')
     # Start sampler
     print('Start Nestle')
     result = nestle.sample(self.calllike,self.prior_trans,self.ndim,method='multi',npoints=1000,callback=self.nestle_callback)
     # generate posterior means and covariances
     p,cov = nestle.mean_and_cov(result.samples,result.weights)
     # close output file
     self.outfile.close()
     return result,p,cov
Exemplo n.º 16
0
def run_nestle(logl, logp, ranges, npoints=1000, method='single'):
    def logprob(p):
        return logl(p) + logp(p)

    def prior_transform(p):
        return (ranges[:, 1] - ranges[:, 0]) * p + ranges[:, 0]

    return nestle.sample(logprob,
                         prior_transform,
                         len(ranges),
                         method=method,
                         npoints=npoints)
Exemplo n.º 17
0
    def _run_test(self):
        """
        Runs to test whether the sampler is properly running with the given
        kwargs without actually running to the end

        Returns
        -------
        bilby.core.result.Result: Dummy container for sampling results.

        """
        import nestle
        kwargs = self.kwargs.copy()
        kwargs['maxiter'] = 2
        nestle.sample(loglikelihood=self.log_likelihood,
                      prior_transform=self.prior_transform,
                      ndim=self.ndim,
                      **kwargs)
        self.result.samples = np.random.uniform(0, 1, (100, self.ndim))
        self.result.log_evidence = np.nan
        self.result.log_evidence_err = np.nan
        return self.result
Exemplo n.º 18
0
    def compute_fit(self):
        """

        Computes the fit using nestle

        """
        data = self._observed.spectrum
        datastd = self._observed.errorBar
        sqrtpi = np.sqrt(2 * np.pi)

        def nestle_loglike(params):
            # log-likelihood function called by multinest
            fit_params_container = np.array(params)
            chi_t = self.chisq_trans(fit_params_container, data, datastd)
            loglike = -np.sum(np.log(datastd * sqrtpi)) - 0.5 * chi_t
            return loglike

        def nestle_uniform_prior(theta):
            # prior distributions called by multinest. Implements a uniform prior
            # converting parameters from normalised grid to uniform prior
            cube = []

            for idx, prior in enumerate(self.fitting_priors):

                cube.append(prior.sample(theta[idx]))

            return tuple(cube)

        ndim = len(self.fitting_parameters)
        self.warning('Beginning fit......')
        ndims = ndim  # two parameters

        t0 = time.time()

        res = nestle.sample(nestle_loglike,
                            nestle_uniform_prior,
                            ndims,
                            method='multi',
                            npoints=self.numLivePoints,
                            dlogz=self.tolerance,
                            callback=nestle.print_progress)
        t1 = time.time()

        timenestle = (t1 - t0)

        print(res.summary())

        self.warning("Time taken to run 'Nestle' is %s seconds", timenestle)

        self.warning('Fit complete.....')

        self._nestle_output = self.store_nestle_output(res)
Exemplo n.º 19
0
 def __start_sampling(self):
     self.__results = nestle.sample(loglikelihood=self.__calc_function,
                                    prior_transform=self.__prior,
                                    ndim=self.__ndim,
                                    npoints=self.__npoints,
                                    method=self.__method,
                                    update_interval=self.__update_interval,
                                    npdim=self.__npdim,
                                    maxiter=self.__maxiter,
                                    maxcall=self.__maxcall,
                                    dlogz=self.__dlogz,
                                    decline_factor=self.__decline_factor,
                                    callback=self.__callback_object)
Exemplo n.º 20
0
def run(ndim):
    """Convenience function for running in any dimension"""

    c1 = np.zeros(ndim)
    c1[0] = -3.5
    c2 = np.zeros(ndim)
    c2[0] = 3.5
    f = lambda theta: loglike(theta, c1, c2)

    return nestle.sample(f,
                         prior_transform,
                         ndim,
                         method='multi',
                         npoints=npoints,
                         rstate=rstate)
Exemplo n.º 21
0
 def __start_sampling(self):
     self.__results = nestle.sample(
         loglikelihood=self.__calc_function,
         prior_transform=self.__prior,
         ndim=self.__ndim,
         npoints=self.__npoints,
         method=self.__method,
         update_interval=self.__update_interval,
         npdim=self.__npdim,
         maxiter=self.__maxiter,
         maxcall=self.__maxcall,
         dlogz=self.__dlogz,
         decline_factor=self.__decline_factor,
         callback=self.__callback_object
     )
Exemplo n.º 22
0
 def run(self, verbose=False):
     """Initiate the Nestle Nested Sampling run."""
     callback = None
     if verbose:
         callback = nestle.print_progress
     output = nestle.sample(self.loglikelihood,
                            self._prior_transform,
                            self._nDims,
                            npoints=self.population_size,
                            callback=callback,
                            **self.nestle_kwargs)
     if verbose:
         output.summary()
     self._output = output
     return self.log_evidence, self.log_evidence_error
Exemplo n.º 23
0
def run_nestle_sampler(lnprobfn,
                       model,
                       verbose=True,
                       callback=None,
                       nestle_method='multi',
                       nestle_npoints=200,
                       nestle_maxcall=int(1e6),
                       nestle_update_interval=None,
                       **kwargs):

    result = nestle.sample(lnprobfn,
                           model.prior_transform,
                           model.ndim,
                           method=nestle_method,
                           npoints=nestle_npoints,
                           callback=callback,
                           maxcall=nestle_maxcall,
                           update_interval=nestle_update_interval)
    return result
def nestle_multi2():
    # Run nested sampling
    res = nestle.sample(loglike2,
                        prior_transform2,
                        2,
                        method='multi',
                        npoints=2000)

    # weighted average and covariance:
    pm, covm = nestle.mean_and_cov(res.samples, res.weights)

    # re-scale weights to have a maximum of one
    nweights = res.weights / np.max(res.weights)

    # get the probability of keeping a sample from the weights
    keepidx = np.where(np.random.rand(len(nweights)) < nweights)[0]

    # get the posterior samples
    samples_nestle = res.samples[keepidx, :]

    return res.logz
Exemplo n.º 25
0
def test_eggbox():
    tmax = 5.0 * np.pi
    constant = np.log(1.0 / tmax**2)

    def loglike(x):
        t = 2.0 * tmax * x - tmax
        return (2.0 + np.cos(t[0]/2.0)*np.cos(t[1]/2.0))**5.0

    def prior(x):
        return x

    res = nestle.sample(loglike, prior, 2, npoints=500, method='multi',
                        rstate=RandomState(0))

    grid_logz = integrate_on_grid_refine(loglike, [(0., 1.), (0., 1.)])

    print("\nEggbox")
    print("multi : logz           = {:6.3f} +/- {:6.3f}"
          .format(res.logz, res.logzerr))
    print("        grid_logz      = {0:8.5f}".format(grid_logz))

    assert abs(res.logz - grid_logz) < 3.0 * res.logzerr
Exemplo n.º 26
0
    def normalise_prior(self,
                        galind,
                        num_components,
                        npoints=50,
                        seed=False,
                        method='multi'):
        #Setup random seeding
        if seed is False:
            rstate = np.random.RandomState()
        elif seed is True:
            rstate = np.random.RandomState(galind)
        else:
            rstate = np.random.RandomState(seed + galind)

        self.model._setMeasurementComponentMapping(num_components)
        results = nestle.sample(
            self._full_lnPrior,
            self._priorTransform,
            num_components * 2,
            method=method,
            npoints=npoints,
            rstate=rstate)  #, callback=self._sampleProgressUpdate)
        self.prior_norm = results.logz
Exemplo n.º 27
0
# import nestle
import nestle
from datetime import datetime

print('Nestle version: {}'.format(nestle.__version__))

nlive = 1024  # number of live points
method = 'multi'  # use MutliNest algorithm
ndims = 9  # two parameters
tol = 0.1  # the stopping criterion

t0 = datetime.now()
res = nestle.sample(log_likelihood,
                    prior_transform,
                    ndims,
                    method=method,
                    npoints=nlive,
                    dlogz=tol)
t1 = datetime.now()

# In[ ]:

timeultranest = (t1 - t0)
print("Time taken to run 'UltraNest' is {} seconds".format(timeultranest))

# In[ ]:

logZultranest = result['logZ']  # value of logZ
logZerrultranest = result[
    'logZerr']  # estimate of the statistcal uncertainty on logZ
Exemplo n.º 28
0
def fit_model_with_nestle(uv_fits, model_file, components_priors, outdir=None,
                          **nestle_kwargs):
    """
    :param uv_fits:
        Path to uv-fits file with self-calibrated visibilities.
    :param model_file:
        Path to file with difmap model.
    :param components_priors:
        Components prior's ppf. Close to phase center component goes first.
        Iterable of dicts with keys - name of the parameter and values -
        (callable, args, kwargs,) where args & kwargs - additional arguments to
        callable. Each callable is called callable.ppf(p, *args, **kwargs).
        Thus callable should has ``ppf`` method.

        Example of prior on single component:
            {'flux': (scipy.stats.uniform.ppf, [0., 10.], dict(),),
             'bmaj': (scipy.stats.uniform.ppf, [0, 5.], dict(),),
             'e': (scipy.stats.beta.ppf, [alpha, beta], dict(),)}
        First key will result in calling: scipy.stats.uniform.ppf(u, 0, 10) as
        value from prior for ``flux`` parameter.
    :param outdir: (optional)
        Directory to output results. If ``None`` then use cwd. (default:
        ``None``)
    :param nestle_kwargs: (optional)
        Any arguments passed to ``nestle.sample`` function.

    :return
        Results of ``nestle.sample`` work on that model.
    """
    if outdir is None:
        outdir = os.getcwd()

    mdl_file = model_file
    uv_data = UVData(uv_fits)
    mdl_dir, mdl_fname = os.path.split(mdl_file)
    comps = import_difmap_model(mdl_fname, mdl_dir)

    # Sort components by distance from phase center
    comps = sorted(comps, key=lambda x: np.sqrt(x.p[1]**2 + x.p[2]**2))

    ppfs = list()
    labels = list()
    for component_prior in components_priors:
        for comp_name in ('flux', 'x', 'y', 'bmaj', 'e', 'bpa'):
            try:
                ppfs.append(_function_wrapper(*component_prior[comp_name]))
                labels.append(comp_name)
            except KeyError:
                pass

    for ppf in ppfs:
        print(ppf.args)

    hypercube = hypercube_partial(ppfs)

    # Create model
    mdl = Model(stokes=stokes)
    # Add components to model
    mdl.add_components(*comps)
    loglike = LnLikelihood(uv_data, mdl)
    time0 = time.time()
    result = nestle.sample(loglikelihood=loglike, prior_transform=hypercube,
                           ndim=mdl.size, npoints=50, method='multi',
                           callback=nestle.print_progress, **nestle_kwargs)
    print("Time spent : {}".format(time.time()-time0))
    samples = nestle.resample_equal(result.samples, result.weights)
    # Save re-weighted samples from posterior to specified ``outdir``
    # directory
    np.savetxt(os.path.join(outdir, 'samples.txt'), samples)
    fig = corner.corner(samples, show_titles=True, labels=labels,
                        quantiles=[0.16, 0.5, 0.84], title_fmt='.3f')
    # Save corner plot os samples from posterior to specified ``outdir``
    # directory
    fig.savefig(os.path.join(outdir, "corner.png"), bbox_inches='tight',
                dpi=200)

    return result
Exemplo n.º 29
0
    def run_multinest(self, wavelength_bins, depths, errors, fit_info,
                      include_condensation=True, plot_best=False,
                      **nestle_kwargs):
        '''Runs nested sampling to retrieve atmospheric parameters.

        Parameters
        ----------
        wavelength_bins : array_like, shape (N,2)
            Wavelength bins, where wavelength_bins[i][0] is the start
            wavelength and wavelength_bins[i][1] is the end wavelength for
            bin i.
        depths : array_like, length N
            Measured transit depths for the specified wavelength bins
        errors : array_like, length N
            Errors on the aforementioned transit depths
        fit_info : :class:`.FitInfo` object
            Tells us what parameters to
            freely vary, and in what range those parameters can vary. Also
            sets default values for the fixed parameters.
        include_condensation : bool, optional
            When determining atmospheric abundances, whether to include
            condensation.
        plot_best : bool, optional
            If True, plots the best fit model with the data
        **nestle_kwargs : keyword arguments to pass to nestle's sample method

        Returns
        -------
        result : Result object
            This returns the object returned by nestle.sample  The object is
            dictionary-like and has many useful items.  For example,
            result.samples (or alternatively, result["samples"]) are the
            parameter values of each sample, result.weights contains the
            weights, and result.logl contains the log likelihoods.  result.logz
            is the natural logarithm of the evidence.
        '''
        calculator = TransitDepthCalculator(
            include_condensation=include_condensation)
        calculator.change_wavelength_bins(wavelength_bins)
        self._validate_params(fit_info, calculator)

        def transform_prior(cube):
            new_cube = np.zeros(len(cube))
            for i in range(len(cube)):
                new_cube[i] = fit_info._from_unit_interval(i, cube[i])
            return new_cube

        def multinest_ln_prob(cube):
            return self._ln_prob(cube, calculator, fit_info, depths, errors)

        def callback(callback_info):
            print(callback_info["it"], callback_info["logz"],
                  transform_prior(callback_info["active_u"][0]))

        result = nestle.sample(
            multinest_ln_prob, transform_prior, fit_info._get_num_fit_params(),
            callback=callback, method='multi', **nestle_kwargs)

        best_params_arr = result.samples[np.argmax(result.logl)]
        
        write_param_estimates_file(
            nestle.resample_equal(result.samples, result.weights),
            best_params_arr,
            np.max(result.logl),
            fit_info.fit_param_names)

        if plot_best:
            self._ln_prob(best_params_arr, calculator, fit_info,
                          depths, errors, plot=True)
        return result
Exemplo n.º 30
0
def prior_transform(x):
    return 7 * np.pi * x  # - 5.0


x = np.arange(0, 7 * np.pi, 0.1)[np.newaxis]
y = np.arange(0, 7 * np.pi, 0.1)
z = np.arange(0, 3, 0.1)

# plt.figure(1)
# plt.imshow(Likelihood([x.T, y]), cmap='hot')
# plt.show()

# Run nested sampling.
result = nestle.sample(Likelihood,
                       prior_transform,
                       3,
                       npoints=1000,
                       method='multi')

result.logz  # log evidence
result.logzerr  # numerical (sampling) error on logz
result.samples  # array of sample parameters
result.weights  # array of weights associated with each sample

plt.figure(2)
plt.plot(result.samples[400:, 0], result.samples[400:, 2], '.')
plt.xlabel('$\\theta_{1}$')
plt.ylabel('$\\theta_{3}$')
plt.ylim(0, 3)
# # plt.hist2d(result.samples[:, 0], result.samples[:, 1], weights=result.weights, bins=20)
plt.show()
Exemplo n.º 31
0
def nest_lc(data, model, vparam_names, bounds, guess_amplitude_bound=False,
            minsnr=5., priors=None, ppfs=None, npoints=100, method='single',
            maxiter=None, maxcall=None, modelcov=False, rstate=None,
            verbose=False, **kwargs):
    """Run nested sampling algorithm to estimate model parameters and evidence.

    Parameters
    ----------
    data : `~astropy.table.Table` or `~numpy.ndarray` or `dict`
        Table of photometric data. Must include certain columns.
        See the "Photometric Data" section of the documentation for
        required columns.
    model : `~sncosmo.Model`
        The model to fit.
    vparam_names : list
        Model parameters to vary in the fit.
    bounds : `dict`
        Bounded range for each parameter. Bounds must be given for
        each parameter, with the exception of ``t0``: by default, the
        minimum bound is such that the latest phase of the model lines
        up with the earliest data point and the maximum bound is such
        that the earliest phase of the model lines up with the latest
        data point.
    guess_amplitude_bound : bool, optional
        If true, bounds for the model's amplitude parameter are determined
        automatically based on the data and do not need to be included in
        `bounds`. The lower limit is set to zero and the upper limit is 10
        times the amplitude "guess" (which is based on the highest-flux
        data point in any band). Default is False.
    minsnr : float, optional
        Minimum signal-to-noise ratio of data points to use when guessing
        amplitude bound. Default is 5.
    priors : `dict`, optional
        Prior probability distribution function for each parameter. The keys
        should be parameter names and the values should be callables that
        accept a float. If a parameter is not in the dictionary, the prior
        defaults to a flat distribution between the bounds.
    ppfs : `dict`, optional
        Prior percent point function (inverse of the cumulative distribution
        function) for each parameter. If a parameter is in this dictionary,
        the ppf takes precedence over a prior pdf specified in ``priors``.
    npoints : int, optional
        Number of active samples to use. Increasing this value increases
        the accuracy (due to denser sampling) and also the time
        to solution.
    method : {'classic', 'single', 'multi'}, optional
        Method used to select new points. Choices are 'classic',
        single-ellipsoidal ('single'), multi-ellipsoidal ('multi'). Default
        is 'single'.
    maxiter : int, optional
        Maximum number of iterations. Iteration may stop earlier if
        termination condition is reached. Default is no limit.
    maxcall : int, optional
        Maximum number of likelihood evaluations. Iteration may stop earlier
        if termination condition is reached. Default is no limit.
    modelcov : bool, optional
        Include model covariance when calculating chisq. Default is False.
    rstate : `~numpy.random.RandomState`, optional
        RandomState instance. If not given, the global random state of the
        ``numpy.random`` module will be used.
    verbose : bool, optional
        Print running evidence sum on a single line.

    Returns
    -------
    res : Result
        Attributes are:

        * ``niter``: total number of iterations
        * ``ncall``: total number of likelihood function calls
        * ``time``: time in seconds spent in iteration loop.
        * ``logz``: natural log of the Bayesian evidence Z.
        * ``logzerr``: estimate of uncertainty in logz (due to finite sampling)
        * ``h``: Bayesian information.
        * ``vparam_names``: list of parameter names varied.
        * ``samples``: 2-d `~numpy.ndarray`, shape is (nsamples, nparameters).
          Each row is the parameter values for a single sample. For example,
          ``samples[0, :]`` is the parameter values for the first sample.
        * ``logprior``: 1-d `~numpy.ndarray` (length=nsamples);
          log(prior volume) for each sample.
        * ``logl``: 1-d `~numpy.ndarray` (length=nsamples); log(likelihood)
          for each sample.
        * ``weights``: 1-d `~numpy.ndarray` (length=nsamples);
          Weight corresponding to each sample. The weight is proportional to
          the prior * likelihood for the sample.
        * ``parameters``: 1-d `~numpy.ndarray` of weighted-mean parameter
          values from samples (including fixed parameters). Order corresponds
          to ``model.param_names``.
        * ``covariance``: 2-d `~numpy.ndarray` of parameter covariance;
          indicies correspond to order of ``vparam_names``. Calculated from
          ``samples`` and ``weights``.
        * ``errors``: OrderedDict of varied parameter uncertainties.
          Corresponds to square root of diagonal entries in covariance matrix.
        * ``ndof``: Number of degrees of freedom (len(data) -
          len(vparam_names)).
        * ``bounds``: Dictionary of bounds on varied parameters (including
          any automatically determined bounds).

    estimated_model : `~sncosmo.Model`
        A copy of the model with parameters set to the values in
        ``res.parameters``.
    """

    try:
        import nestle
    except ImportError:
        raise ImportError("nest_lc() requires the nestle package.")

    if "nobj" in kwargs:
        warn("The nobj keyword is deprecated and will be removed in a future "
             "sncosmo release. Use `npoints` instead.")
        npoints = kwargs.pop("nobj")

    # experimental parameters
    tied = kwargs.get("tied", None)

    data = photometric_data(data)
    data.sort_by_time()
    model = copy.copy(model)
    bounds = copy.copy(bounds)  # need to copy this b/c we modify it below

    # Order vparam_names the same way it is ordered in the model:
    vparam_names = [s for s in model.param_names if s in vparam_names]

    # Drop data that the model doesn't cover.
    data = cut_bands(data, model, z_bounds=bounds.get('z', None))

    if guess_amplitude_bound:
        if model.param_names[2] not in vparam_names:
            raise ValueError("Amplitude bounds guessing enabled but "
                             "amplitude parameter {0!r} is not varied"
                             .format(model.param_names[2]))
        if model.param_names[2] in bounds:
            raise ValueError("cannot supply bounds for parameter {0!r}"
                             " when guess_amplitude_bound=True"
                             .format(model.param_names[2]))

        # If redshift is bounded, set model redshift to midpoint of bounds
        # when doing the guess.
        if 'z' in bounds:
            model.set(z=sum(bounds['z']) / 2.)
        _, amplitude = guess_t0_and_amplitude(data, model, minsnr)
        bounds[model.param_names[2]] = (0., 10. * amplitude)

    # Find t0 bounds to use, if not explicitly given
    if 't0' in vparam_names and 't0' not in bounds:
        bounds['t0'] = t0_bounds(data, model)

    if ppfs is None:
        ppfs = {}
    if tied is None:
        tied = {}

    # Convert bounds/priors combinations into ppfs
    if bounds is not None:
        for key, val in six.iteritems(bounds):
            if key in ppfs:
                continue  # ppfs take priority over bounds/priors
            a, b = val
            if priors is not None and key in priors:
                # solve ppf at discrete points and return interpolating
                # function
                x_samples = np.linspace(0., 1., 101)
                ppf_samples = ppf(priors[key], x_samples, a, b)
                f = Interp1D(0., 1., ppf_samples)
            else:
                f = Interp1D(0., 1., np.array([a, b]))
            ppfs[key] = f

    # NOTE: It is important that iparam_names is in the same order
    # every time, otherwise results will not be reproducible, even
    # with same random seed.  This is because iparam_names[i] is
    # matched to u[i] below and u will be in a reproducible order,
    # so iparam_names must also be.
    iparam_names = [key for key in vparam_names if key in ppfs]
    ppflist = [ppfs[key] for key in iparam_names]
    npdim = len(iparam_names)  # length of u
    ndim = len(vparam_names)  # length of v

    # Check that all param_names either have a direct prior or are tied.
    for name in vparam_names:
        if name in iparam_names:
            continue
        if name in tied:
            continue
        raise ValueError("Must supply ppf or bounds or tied for parameter '{}'"
                         .format(name))

    def prior_transform(u):
        d = {}
        for i in range(npdim):
            d[iparam_names[i]] = ppflist[i](u[i])
        v = np.empty(ndim, dtype=np.float)
        for i in range(ndim):
            key = vparam_names[i]
            if key in d:
                v[i] = d[key]
            else:
                v[i] = tied[key](d)
        return v

    # Indicies of the model parameters in vparam_names
    idx = np.array([model.param_names.index(name) for name in vparam_names])

    def loglike(parameters):
        model.parameters[idx] = parameters
        return -0.5 * chisq(data, model, modelcov=modelcov)

    t0 = time.time()
    res = nestle.sample(loglike, prior_transform, ndim, npdim=npdim,
                        npoints=npoints, method=method, maxiter=maxiter,
                        maxcall=maxcall, rstate=rstate,
                        callback=(nestle.print_progress if verbose else None))
    elapsed = time.time() - t0

    # estimate parameters and covariance from samples
    vparameters, cov = nestle.mean_and_cov(res.samples, res.weights)

    # update model parameters to estimated ones.
    model.set(**dict(zip(vparam_names, vparameters)))

    # `res` is a nestle.Result object. Collect result into a sncosmo.Result
    # object for consistency, and add more fields.
    res = Result(niter=res.niter,
                 ncall=res.ncall,
                 logz=res.logz,
                 logzerr=res.logzerr,
                 h=res.h,
                 samples=res.samples,
                 weights=res.weights,
                 logvol=res.logvol,
                 logl=res.logl,
                 vparam_names=copy.copy(vparam_names),
                 ndof=len(data) - len(vparam_names),
                 bounds=bounds,
                 time=elapsed,
                 parameters=model.parameters.copy(),
                 covariance=cov,
                 errors=OrderedDict(zip(vparam_names,
                                        np.sqrt(np.diagonal(cov)))),
                 param_dict=OrderedDict(zip(model.param_names,
                                            model.parameters)))

    # Deprecated result fields.
    depmsg = ("The `param_names` attribute is deprecated in sncosmo v1.0 "
              "and will be removed in a future release. "
              "Use `vparam_names` instead.")
    res.__dict__['deprecated']['param_names'] = (res.vparam_names, depmsg)

    depmsg = ("The `logprior` attribute is deprecated in sncosmo v1.2 "
              "and will be changed in a future release. "
              "Use `logvol` instead.")
    res.__dict__['deprecated']['logprior'] = (res.logvol, depmsg)

    return res, model
Exemplo n.º 32
0
def sample(loglike_model, prior_transform_model, datafile, priorRange):
    """
The function runs nested sampling. The function can be run on 4 different models. The user just needs to specify the model's loglikelihood and prior. 
----------    
The following input parameters are required:
    
loglike_model: function calculates likelihood. The name of the loglike_model needs to be specified. 
prior_transform_model: function calculates the prior. The name of the prior transformation function needs to be specified. 
datafile: datafile with format has been discussed in above. 
priorRange: an array which specifies the limits of unifrom prior for different parameters eg: priorRange =[rangeForTheta[0],rangeForTheta[1],...]
  
----------
Here are some example commands for running the fuction for 4 different models.    

    model.sample (model.loglike_NFW, model.prior_transform_NFW, 'DMdataref1.txt',[10,10E10])
    model.sample (model.loglike_ISO, model.prior_transform_ISO, 'DMdataref1.txt',[10,10E10])
    model.sample (model.loglike_Einasto, model.prior_transform_Einasto, 'DMdataref1.txt',[10,10,10E10])
    model.sample (model.loglike_GeneralizedHalo, model.prior_transform_GeneralizedHalo, 'DMdataref1.txt',[5.,10.,4.,1.5,5E8])
-----------
As shown above, different models take in different loglike_model, prior_transform_model and priorRange. 

For NFW model: 
loglike_model: it's named as 'model.loglike_NFW'
prior_transform_model: it's named as 'model.prior_transform_NFW'
datafile: any datafile that has the correct 4 columns format. 
priorRange: an arrange of 2 elements. Recommand to use [10,10e10]


For ISO model: 
loglike_model: it's named as 'model.loglike_ISO'
prior_transform_model: it's named as 'model.prior_transform_ISO'
datafile: any datafile that has the correct 4 columns format. 
priorRange: an arrange of 2 elements. Recommand to use [10,10e10]

For Einasto model: 
loglike_model: it's named as 'model.loglike_Einasto'
prior_transform_model: it's named as 'model.prior_transform_Einasto'
datafile: any datafile that has the correct 4 columns format. 
priorRange: an arrange of 3 elements. Recommand to use [10,10,10e10]

For GeneralizedHalo model: 
loglike_model: it's named as 'model.loglike_GeneralizedHalo'
prior_transform_model: it's named as 'model.prior_transform_GeneralizedHalo'
datafile: any datafile that has the correct 4 columns format. 
priorRange: an arrange of 5 elements. Recommand to use [5.,10.,4.,1.5,5e8]

 
    """

    data_file = io.get_data_file_path(datafile)
    data_x, data_xerr, data_y, data_yerr = io.load_data(data_file)

    #n: number of parameters, len(priorRange)
    n = len(priorRange)

    def new_loglike_model(theta):
        return loglike_model(theta, (data_x, data_xerr, data_y, data_yerr))

    def new_prior_transform_model(theta):
        return prior_transform_model(theta, priorRange)

    result = nestle.sample(new_loglike_model, new_prior_transform_model, n)

    print('log evidence')
    print(result.logz)

    print('numerical (sampling) error on logz')
    print(result.logzerr)

    print('array of sample parameters')
    print(result.samples)

    print('array of weights associated with each sample')
    print(result.weights)

    return result
Exemplo n.º 33
0
    m, c = theta # unpack the parameters

    # normalisation
    norm = -0.5*M*LN2PI - M*LNSIGMA

    # chi-squared (data, sigma and x are global variables defined early on in this notebook)
    chisq = np.sum(((data-straight_line(x, m, c))/sigma)**2)

    return norm - 0.5*chisq

nlive = 1024     # number of live points
method = 'multi' # use MutliNest algorithm
ndims = 2        # two parameters
tol= 0.5         # the stopping criterion (this is the nestle default, so doesn't need to be set)

res = nestle.sample(loglikelihood_nestle, prior_transform, ndims, method=method, npoints=nlive, dlogz=tol)

logZnestle = res.logz                         # value of logZ
infogainnestle = res.h                        # value of the information gain in nats
logZerrnestle = np.sqrt(infogainnestle/nlive) # estimate of the statistcal uncertainty on logZ

# output marginal likelihood
print('Marginalised evidence is {} ± {}'.format(logZnestle, logZerrnestle))

# re-scale weights to have a maximum of one
nweights = res.weights/np.max(res.weights)

# get the probability of keeping a sample from the weights
keepidx = np.where(np.random.rand(len(nweights)) < nweights)[0]

# get the posterior samples
Exemplo n.º 34
0
# It helps to visualize the surface in two dimensions. Here, we plot the
# likelihood evaluated on a fine grid and the sample points from nested
# sampling.

# likelihood surface in 2-d
xx, yy = np.meshgrid(np.linspace(-6., 6., 200),
                     np.linspace(-6., 6., 200))
c1 = np.array([-3.5, 0.])
c2 = np.array([3.5, 0.])
Z = np.exp(loglike(np.dstack((xx, yy)), c1, c2))

# nested sampling result
c1 = np.array([-3.5, 0.])
c2 = np.array([3.5, 0.])
f = lambda theta: loglike(theta, c1, c2)
res = nestle.sample(f, prior_transform, 2, method='multi', npoints=1000,
                    rstate=rstate)

fig = plt.figure(figsize=(14., 6.))
ax = fig.add_subplot(121, projection='3d')
ax.plot_surface(xx, yy, Z, rstride=1, cstride=1, linewidth=0, cmap='coolwarm')
ax.set_xlim(-6., 6.)
ax.set_ylim(-6., 6.)
ax.set_zlim(0., 4.)
ax.set_zlabel('L')
ax.set_title('Likelihood evaluated on fine grid')

ax = fig.add_subplot(122, projection='3d')
ax.scatter(res.samples[:,0], res.samples[:, 1], np.exp(res.logl),
           marker='.', c=np.exp(res.logl), linewidths=(0.,), cmap='coolwarm')
ax.set_xlim(-6., 6.)
ax.set_ylim(-6., 6.)
Exemplo n.º 35
0
yerr = 0.1 + 0.5 * np.random.rand(N)
y += yerr * np.random.randn(N)


# The likelihood function:
def loglike(theta):
    return -0.5 * (np.sum((y - model(theta, x))**2 / yerr**2))


# Defines a flat prior in 0 < m < 1, 0 < b < 100:
def prior_transform(theta):
    return np.array([1., 100.]) * theta


# Run nested sampling
res = nestle.sample(loglike, prior_transform, 2, method='single', npoints=1000)
print(res.summary())

# weighted average and covariance:
p, cov = nestle.mean_and_cov(res.samples, res.weights)

print("m = {0:5.2f} +/- {1:5.2f}".format(p[0], np.sqrt(cov[0, 0])))
print("b = {0:5.2f} +/- {1:5.2f}".format(p[1], np.sqrt(cov[1, 1])))

plt.figure()
plt.errorbar(x, y, yerr=yerr, capsize=0, fmt='k.', ecolor='.7')
plt.plot([0., 10.], model(p, np.array([0., 10.])), c='k')
plt.show()

###############################################################################
# Plot samples to see the full posterior surface.
Exemplo n.º 36
0
def nested_negfc_sampling(init,
                          cube,
                          angs,
                          plsc,
                          psf,
                          fwhm,
                          annulus_width=8,
                          aperture_radius=1,
                          ncomp=10,
                          scaling=None,
                          svd_mode='lapack',
                          cube_ref=None,
                          collapse='median',
                          w=(5, 5, 200),
                          method='single',
                          npoints=100,
                          dlogz=0.1,
                          decline_factor=None,
                          rstate=None,
                          verbose=True):
    """ Runs a nested sampling algorithm in order to determine the position and
    the flux of the planet using the 'Negative Fake Companion' technique. The
    result of this procedure is a a ``nestle`` object containing the samples
    from the posterior distributions of each of the 3 parameters. It provides
    pretty good results (value plus error bars) compared to a more CPU intensive
    Monte Carlo approach with the affine invariant sampler (``emcee``).

    Parameters
    ----------
    init: numpy ndarray or tuple of length 3
        The first guess for the position and flux of the planet, respectively.
        It serves for generating the bounds of the log prior function (uniform
        in a bounded interval).
    cube: numpy ndarray
        Frame sequence of cube.
    angs: numpy ndarray
        The relative path to the parallactic angle fits image or the angs itself.
    plsc: float
        The platescale, in arcsec per pixel.
    psf: numpy ndarray
        The PSF template. It must be centered and the flux in a 1*FWHM aperture
        must equal 1.
    fwhm : float
        The FHWM in pixels.
    annulus_width: float, optional
        The width in pixel of the annulus on which the PCA is performed.
    aperture_radius: float, optional
        The radius of the circular aperture in FWHM.
    ncomp: int optional
        The number of principal components.
    scaling : {'temp-mean', 'temp-standard'} or None, optional
        With None, no scaling is performed on the input data before SVD. With
        "temp-mean" then temporal px-wise mean subtraction is done and with
        "temp-standard" temporal mean centering plus scaling to unit variance
        is done.
    svd_mode : {'lapack', 'randsvd', 'eigen', 'arpack'}, str optional
        Switch for different ways of computing the SVD and selected PCs.
    cube_ref: numpy ndarray, 3d, optional
        Reference library cube. For Reference Star Differential Imaging.
    collapse : {'median', 'mean', 'sum', 'trimmean', None}, str or None, optional
        Sets the way of collapsing the frames for producing a final image. If
        None then the cube of residuals is used when measuring the function of
        merit (instead of a single final frame).
    w : tuple of length 3
        The size of the bounds (around the initial state ``init``) for each
        parameter.
    method : {"single", "multi", "classic"}, str optional
        Flavor of nested sampling. Single ellipsoid works well for the NEGFC and
        is the default.
    npoints : int optional
        Number of active points. At least ndim+1 (4 will produce bad results).
        For problems with just a few parameters (<=5) like the NEGFC, good
        results are obtained with 100 points (default).
    dlogz : Estimated remaining evidence
        Iterations will stop when the estimated contribution of the remaining
        prior volume to the total evidence falls below this threshold.
        Explicitly, the stopping criterion is log(z + z_est) - log(z) < dlogz
        where z is the current evidence from all saved samples, and z_est is the
        estimated contribution from the remaining volume. This option and
        decline_factor are mutually exclusive. If neither is specified, the
        default is dlogz=0.5.
    decline_factor : float, optional
        If supplied, iteration will stop when the weight (likelihood times prior
        volume) of newly saved samples has been declining for
        decline_factor * nsamples consecutive samples. A value of 1.0 seems to
        work pretty well.
    rstate : random instance, optional
        RandomState instance. If not given, the global random state of the
        numpy.random module will be used.

    Returns
    -------
    res : nestle object
        ``Nestle`` object with the nested sampling results, including the
        posterior samples.

    Notes
    -----
    Nested Sampling is a computational approach for integrating posterior
    probability in order to compare models in Bayesian statistics. It is similar
    to Markov Chain Monte Carlo (MCMC) in that it generates samples that can be
    used to estimate the posterior probability distribution. Unlike MCMC, the
    nature of the sampling also allows one to calculate the integral of the
    distribution. It also happens to be a pretty good method for robustly
    finding global maxima.

    Nestle documentation:
    http://kbarbary.github.io/nestle/

    Convergence:
    http://kbarbary.github.io/nestle/stopping.html
    Nested sampling has no well-defined stopping point. As iterations continue,
    the active points sample a smaller and smaller region of prior space.
    This can continue indefinitely. Unlike typical MCMC methods, we don't gain
    any additional precision on the results by letting the algorithm run longer;
    the precision is determined at the outset by the number of active points.
    So, we want to stop iterations as soon as we think the active points are
    doing a pretty good job sampling the remaining prior volume - once we've
    converged to the highest-likelihood regions such that the likelihood is
    relatively flat within the remaining prior volume.

    Method:
    The trick in nested sampling is to, at each step in the algorithm,
    efficiently choose a new point in parameter space drawn with uniform
    probability from the parameter space with likelihood greater than the
    current likelihood constraint. The different methods all use the
    current set of active points as an indicator of where the target
    parameter space lies, but differ in how they select new points from  it.
    "classic" is close to the method described in Skilling (2004).
    "single", Mukherjee, Parkinson & Liddle (2006), Determines a single
    ellipsoid that bounds all active points,
    enlarges the ellipsoid by a user-settable factor, and selects a new point
    at random from within the ellipsoid.
    "multiple", Shaw, Bridges & Hobson (2007) and Feroz, Hobson & Bridges 2009
    (Multinest). In cases where the posterior is multi-modal,
    the single-ellipsoid method can be extremely inefficient: In such
    situations, there are clusters of active points on separate
    high-likelihood regions separated by regions of lower likelihood.
    Bounding all points in a single ellipsoid means that the ellipsoid
    includes the lower-likelihood regions we wish to avoid
    sampling from.
    The solution is to detect these clusters and bound them in separate
    ellipsoids. For this, we use a recursive process where we perform
    K-means clustering with K=2. If the resulting two ellipsoids have a
    significantly lower total volume than the parent ellipsoid (less than half),
    we accept the split and repeat the clustering and volume test on each of
    the two subset of points. This process continues recursively.
    Alternatively, if the total ellipse volume is significantly greater
    than expected (based on the expected density of points) this indicates
    that there may be more than two clusters and that K=2 was not an
    appropriate cluster division.
    We therefore still try to subdivide the clusters recursively. However,
    we still only accept the final split into N clusters if the total volume
    decrease is significant.

    """
    def prior_transform(x):
        """ x:[0,1]

        The prior transform is dinamically created with these bound:
        [radius-w1:radius+w1], [theta-w2:theta+w2], [flux-w3:flux+w3]

        Notes
        -----
        The prior transform function is used to specify the Bayesian prior for the
        problem, in a round-about way. It is a transformation from a space where
        variables are independently and uniformly distributed between 0 and 1 to
        the parameter space of interest. For independent parameters, this would be
        the product of the inverse cumulative distribution function (also known as
        the percent point function or quantile function) for each parameter.
        http://kbarbary.github.io/nestle/prior.html

        """
        a1 = 2 * w[0]
        a2 = init[0] - w[0]
        b1 = 2 * w[1]
        b2 = init[1] - w[1]
        c1 = 2 * w[2]
        c2 = init[2] - w[2]
        return np.array([a1 * x[0] + a2, b1 * x[1] + b2, c1 * x[2] + c2])

    def f(param):
        return lnlike(param=param,
                      cube=cube,
                      angs=angs,
                      plsc=plsc,
                      psf_norm=psf,
                      fwhm=fwhm,
                      annulus_width=annulus_width,
                      aperture_radius=aperture_radius,
                      initial_state=init,
                      cube_ref=cube_ref,
                      svd_mode=svd_mode,
                      scaling=scaling,
                      fmerit='sum',
                      ncomp=ncomp,
                      collapse=collapse)

    # -------------------------------------------------------------------------
    if verbose: start = time_ini()

    if verbose:
        print('Prior bounds on parameters:')
        print('Radius [{},{}]'.format(
            init[0] - w[0],
            init[0] + w[0],
        ))
        print('Theta [{},{}]'.format(init[1] - w[1], init[1] + w[1]))
        print('Flux [{},{}]'.format(init[2] - w[2], init[2] + w[2]))
        print('\nUsing {} active points'.format(npoints))

    res = nestle.sample(f,
                        prior_transform,
                        ndim=3,
                        method=method,
                        npoints=npoints,
                        rstate=rstate,
                        dlogz=dlogz,
                        decline_factor=decline_factor)

    # if verbose:  print; timing(start)
    if verbose:
        print('\nTotal running time:')
        timing(start)
    return res
Exemplo n.º 37
0
    def sample(self,
               num_components,
               galaxy=None,
               nresample=1000,
               seed=False,
               mc_map_matrix=None,
               npoints=150,
               print_interval=10,
               use_pymultinest=None,
               save_path=None,
               save_interval=None):
        """Sample the posterior for a particular number of components.

        Args:
            num_components (int):
                Sample the posterior defined for this number of components in the source.

            galaxy (int or None):
                Index of the galaxy to sample. If None, sample every galaxy in the
                photometry. Defaults to None.

            nresample (int):
                Number of non-weighted samples to draw from the weighted samples
                distribution from Nested Sampling. Defaults to 1000.

            seed (bool or int):
                Random seed for sampling to ensure deterministic results when
                ampling again. If False, do not seed. If True, seed with value
                derived from galaxy index. If int, seed with specific value.

            mc_map_matrix (None or list of tuples):
                If None, sample from the fully blended posterior. For a partially
                blended posterior, this should be a list of tuples (length = number of
                measurements), where each tuples contains the (zero-based) indices of
                the components that measurement contains. Defaults to None.

            npoints (int):
                Number of live points for the Nested Sampling algorithm. Defaults to 150.

            print_interval (int):
                Update the progress bar with number of posterior evaluations every
                print_interval calls. Defaults to 10.

            save_path (None or str):
                Filepath for saving the Photoz object for reloading with `Photoz.loadState`.
                If None, do not automatically save. If given, the Photoz object will
                be saved to this path after all galaxies are sampled. If save_interval
                is also not None, the Photoz object will be saved to this path every
                save_interval galaxies. Defaults to None.

            save_interval (None or int)
                If given and save_path is not None, the Photoz object will be
                saved to save_path every save_interval galaxies. Defaults to None.

            use_pymultinest (bool or None)
                If True, sample using the pyMultinest sampler. This requires PyMultiNest
                to be installed separately. If False, sample using the Nestle sampler,
                which is always installed when blendz is. If None, check whether pyMultinest
                is installed and use it if it is, otherwise use Nestle. Defaults to None.
        """

        if use_pymultinest is None:
            use_pymultinest = PYMULTINEST_AVAILABLE

        if isinstance(num_components, int):
            num_components = [num_components]
        else:
            if mc_map_matrix is not None:
                #TODO: This is a time-saving hack to avoid dealing with multiple specifications
                #The solution would probably be to rethink the overall design
                raise ValueError(
                    'mc_map_matrix cannot be set when sampling multiple numbers of components in one call. Do the separate cases separately.'
                )

        self.num_components_sampling = len(num_components)
        self.num_between_print = float(round(print_interval))

        if galaxy is None:
            start = None
            stop = None
            self.num_galaxies_sampling = self.num_galaxies
        elif isinstance(galaxy, int):
            start = galaxy
            stop = galaxy + 1
            self.num_galaxies_sampling = 1
        else:
            raise TypeError(
                'galaxy may be either None or an integer, but got {} instead'.
                format(type(galaxy)))

        with tqdm(total=self.num_galaxies_sampling,
                  unit='galaxy') as self.pbar:
            self.gal_count = 1
            for gal in self.photometry.iterate(start, stop):
                self.blend_count = 1
                for nb in num_components:

                    if seed is False:
                        rstate = np.random.RandomState()
                    elif seed is True:
                        rstate = np.random.RandomState(gal.index)
                    else:
                        rstate = np.random.RandomState(seed + gal.index)

                    num_param = 2 * nb
                    self.model._setMeasurementComponentMapping(nb)

                    self.normalise_prior(gal.index, nb)

                    if use_pymultinest:
                        if not os.path.exists('chains'):
                            os.makedirs('chains')
                        with Silence() as self.breakSilence:
                            self.num_posterior_evals = 0
                            pymultinest.run(self._lnPosterior_multinest,
                                            self._priorTransform_multinest,
                                            num_param,
                                            resume=False,
                                            verbose=False,
                                            sampling_efficiency='model',
                                            n_live_points=npoints)  #,
                            #outputfiles_basename=os.path.join(blendz.CHAIN_PATH, 'chain_'))
                            results = pymultinest.analyse.Analyzer(
                                num_param
                            )  #, outputfiles_basename=os.path.join(blendz.CHAIN_PATH, 'chain_'))

                        self._samples[gal.index][
                            nb] = results.get_equal_weighted_posterior(
                            )[:, :-1]
                        self._logevd[gal.index][nb] = results.get_mode_stats(
                        )['global evidence']
                        self._logevd_error[
                            gal.index][nb] = results.get_mode_stats(
                            )['global evidence error']

                    else:
                        results = nestle.sample(
                            self._lnPosterior,
                            self._priorTransform,
                            num_param,
                            method='multi',
                            npoints=npoints,
                            rstate=rstate,
                            callback=self._sampleProgressUpdate)
                        self._samples[gal.index][nb] = results.samples[
                            rstate.choice(len(results.weights),
                                          size=nresample,
                                          p=results.weights)]
                        self._logevd[gal.index][nb] = results.logz
                        self._logevd_error[gal.index][nb] = results.logzerr

                    self.blend_count += 1

                self.gal_count += 1
                if MPI_RANK == 0:
                    self.pbar.update()
                if (save_path is not None) and (save_interval is not None):
                    if gal.index % save_interval == 0:
                        self.saveState(save_path)
        if save_path is not None:
            self.saveState(save_path)
Exemplo n.º 38
0
 def sample(self):
     res = nestle.sample(self.logLikelihood, self.prior_transform, self.nNodes*36, method='single', npoints=1000)
Exemplo n.º 39
0
def nested_negfc_sampling(init, cube, angs, plsc, psf, fwhm, annulus_width=2,
                          aperture_radius=1, ncomp=10, scaling=None,
                          svd_mode='lapack', cube_ref=None, collapse='median',
                          w=(5, 5, 200), method='single', npoints=100,
                          dlogz=0.1, decline_factor=None, rstate=None,
                          verbose=True):
    """ Runs a nested sampling algorithm in order to determine the position and
    the flux of the planet using the 'Negative Fake Companion' technique. The
    result of this procedure is a a ``nestle`` object containing the samples
    from the posterior distributions of each of the 3 parameters. It provides
    pretty good results (value plus error bars) compared to a more CPU intensive
    Monte Carlo approach with the affine invariant sampler (``emcee``).

    Parameters
    ----------
    init: array_like or tuple of length 3
        The first guess for the position and flux of the planet, respectively.
        It serves for generating the bounds of the log prior function (uniform
        in a bounded interval).
    cube: array_like
        Frame sequence of cube.
    angs: array_like
        The relative path to the parallactic angle fits image or the angs itself.
    plsc: float
        The platescale, in arcsec per pixel.
    psf: array_like
        The PSF template. It must be centered and the flux in a 1*FWHM aperture
        must equal 1.
    fwhm : float
        The FHWM in pixels.
    annulus_width: float, optional
        The width in pixel of the annulus on which the PCA is performed.
    aperture_radius: float, optional
        The radius of the circular aperture.
    ncomp: int optional
        The number of principal components.
    scaling : {'temp-mean', 'temp-standard'} or None, optional
        With None, no scaling is performed on the input data before SVD. With
        "temp-mean" then temporal px-wise mean subtraction is done and with
        "temp-standard" temporal mean centering plus scaling to unit variance
        is done.
    svd_mode : {'lapack', 'randsvd', 'eigen', 'arpack'}, str optional
        Switch for different ways of computing the SVD and selected PCs.
    cube_ref: array_like, 3d, optional
        Reference library cube. For Reference Star Differential Imaging.
    collapse : {'median', 'mean', 'sum', 'trimmean', None}, str or None, optional
        Sets the way of collapsing the frames for producing a final image. If
        None then the cube of residuals is used when measuring the function of
        merit (instead of a single final frame).
    w : tuple of length 3
        The size of the bounds (around the initial state ``init``) for each
        parameter.
    method : {"single", "multi", "classic"}, str optional
        Flavor of nested sampling. Single ellipsoid works well for the NEGFC and
        is the default.
    npoints : int optional
        Number of active points. At least ndim+1 (4 will produce bad results).
        For problems with just a few parameters (<=5) like the NEGFC, good
        results are obtained with 100 points (default).
    dlogz : Estimated remaining evidence
        Iterations will stop when the estimated contribution of the remaining
        prior volume to the total evidence falls below this threshold.
        Explicitly, the stopping criterion is log(z + z_est) - log(z) < dlogz
        where z is the current evidence from all saved samples, and z_est is the
        estimated contribution from the remaining volume. This option and
        decline_factor are mutually exclusive. If neither is specified, the
        default is dlogz=0.5.
    decline_factor : float, optional
        If supplied, iteration will stop when the weight (likelihood times prior
        volume) of newly saved samples has been declining for
        decline_factor * nsamples consecutive samples. A value of 1.0 seems to
        work pretty well.
    rstate : random instance, optional
        RandomState instance. If not given, the global random state of the
        numpy.random module will be used.

    Returns
    -------
    res : nestle object
        ``Nestle`` object with the nested sampling results, including the
        posterior samples.

    Notes
    -----
    Nested Sampling is a computational approach for integrating posterior
    probability in order to compare models in Bayesian statistics. It is similar
    to Markov Chain Monte Carlo (MCMC) in that it generates samples that can be
    used to estimate the posterior probability distribution. Unlike MCMC, the
    nature of the sampling also allows one to calculate the integral of the
    distribution. It also happens to be a pretty good method for robustly
    finding global maxima.

    Nestle documentation:
    http://kbarbary.github.io/nestle/

    Convergence:
    http://kbarbary.github.io/nestle/stopping.html
    Nested sampling has no well-defined stopping point. As iterations continue,
    the active points sample a smaller and smaller region of prior space.
    This can continue indefinitely. Unlike typical MCMC methods, we don't gain
    any additional precision on the results by letting the algorithm run longer;
    the precision is determined at the outset by the number of active points.
    So, we want to stop iterations as soon as we think the active points are
    doing a pretty good job sampling the remaining prior volume - once we've
    converged to the highest-likelihood regions such that the likelihood is
    relatively flat within the remaining prior volume.

    Method:
    The trick in nested sampling is to, at each step in the algorithm,
    efficiently choose a new point in parameter space drawn with uniform
    probability from the parameter space with likelihood greater than the
    current likelihood constraint. The different methods all use the
    current set of active points as an indicator of where the target
    parameter space lies, but differ in how they select new points from  it.
    "classic" is close to the method described in Skilling (2004).
    "single", Mukherjee, Parkinson & Liddle (2006), Determines a single
    ellipsoid that bounds all active points,
    enlarges the ellipsoid by a user-settable factor, and selects a new point
    at random from within the ellipsoid.
    "multiple", Shaw, Bridges & Hobson (2007) and Feroz, Hobson & Bridges 2009
    (Multinest). In cases where the posterior is multi-modal,
    the single-ellipsoid method can be extremely inefficient: In such
    situations, there are clusters of active points on separate
    high-likelihood regions separated by regions of lower likelihood.
    Bounding all points in a single ellipsoid means that the ellipsoid
    includes the lower-likelihood regions we wish to avoid
    sampling from.
    The solution is to detect these clusters and bound them in separate
    ellipsoids. For this, we use a recursive process where we perform
    K-means clustering with K=2. If the resulting two ellipsoids have a
    significantly lower total volume than the parent ellipsoid (less than half),
    we accept the split and repeat the clustering and volume test on each of
    the two subset of points. This process continues recursively.
    Alternatively, if the total ellipse volume is significantly greater
    than expected (based on the expected density of points) this indicates
    that there may be more than two clusters and that K=2 was not an
    appropriate cluster division.
    We therefore still try to subdivide the clusters recursively. However,
    we still only accept the final split into N clusters if the total volume
    decrease is significant.

    """

    def prior_transform(x):
        """ x:[0,1]

        The prior transform is dinamically created with these bound:
        [radius-w1:radius+w1], [theta-w2:theta+w2], [flux-w3:flux+w3]

        Notes
        -----
        The prior transform function is used to specify the Bayesian prior for the
        problem, in a round-about way. It is a transformation from a space where
        variables are independently and uniformly distributed between 0 and 1 to
        the parameter space of interest. For independent parameters, this would be
        the product of the inverse cumulative distribution function (also known as
        the percent point function or quantile function) for each parameter.
        http://kbarbary.github.io/nestle/prior.html

        """
        a1 = 2 * w[0]
        a2 = init[0] - w[0]
        b1 = 2 * w[1]
        b2 = init[1] - w[1]
        c1 = 2 * w[2]
        c2 = init[2] - w[2]
        return np.array([a1 * x[0] + a2, b1 * x[1] + b2, c1 * x[2] + c2])

    def f(param):
        return lnlike(param=param, cube=cube, angs=angs, plsc=plsc,
                      psf_norm=psf, fwhm=fwhm, annulus_width=annulus_width,
                      aperture_radius=aperture_radius, initial_state=init,
                      cube_ref=cube_ref, svd_mode=svd_mode, scaling=scaling,
                      fmerit='sum', ncomp=ncomp, collapse=collapse)

    # -------------------------------------------------------------------------
    if verbose:  start = time_ini()

    if verbose:
        print('Prior bounds on parameters:')
        print('Radius [{},{}]'.format(init[0] - w[0], init[0] + w[0], ))
        print('Theta [{},{}]'.format(init[1] - w[1], init[1] + w[1]))
        print('Flux [{},{}]'.format(init[2] - w[2], init[2] + w[2]))
        print('\nUsing {} active points'.format(npoints))

    res = nestle.sample(f, prior_transform, ndim=3, method=method,
                        npoints=npoints, rstate=rstate, dlogz=dlogz,
                        decline_factor=decline_factor)

    # if verbose:  print; timing(start)
    if verbose:
        print('\nTotal running time:')
        timing(start)
    return res
Exemplo n.º 40
0
	def run_nestle(self,samplertype=None,npoints=None,restart=None,weightrestart=True,maxrejcall=None):
		if samplertype == None:
			samplertype = 'multi'
		if npoints == None:
			npoints = 100

		if restart == None:
			# generate initial random sample within Nestle volume
			modind = np.array(range(0,len(self.MODPARS)),dtype=int)
			selind = modind[np.random.choice(len(modind),npoints,replace=False)]
			
			if ('Tycho_V' in self.bfpar.keys()) & ('Tycho_B' in self.bfpar.keys()):
				cond = (
					(self.PHOT['Tycho_V']+self.DM(self.mindist+0.5*self.distran) > self.bfpar['Tycho_V']-1.0) & 
					(self.PHOT['Tycho_V']+self.DM(self.mindist+0.5*self.distran) < self.bfpar['Tycho_V'] + 1.0) &
					(self.PHOT['Tycho_B']+self.DM(self.mindist+0.5*self.distran) > self.bfpar['Tycho_B']-1.0) & 
					(self.PHOT['Tycho_B']+self.DM(self.mindist+0.5*self.distran) < self.bfpar['Tycho_B'] + 1.0)
					)

				addind = modind[cond][np.random.choice(len(modind[cond]),int(npoints*0.25),replace=False)]
				finind = np.hstack([selind,addind])
				finind = np.unique(finind)
			else:
				finind = selind

			initsample = self.MODPARS[finind]
			initsample_v = np.empty((len(initsample), self.ndim), dtype=np.float64)
			initsample_u = np.empty((len(initsample), self.ndim), dtype=np.float64)

			for i in range(len(initsample)):
				initsample_v_i = [float(initsample['EEP'][i]),10.0**(float(initsample['log_age'][i])-9.0),float(initsample['[Fe/H]in'][i])]
				if self.fitphotbool:
					# initsample_v_i.append(self.distran*np.random.rand()+self.mindist)
					# initsample_v_i.append(self.Avran*np.random.rand()+self.minAv)
					if 'Para' in self.priordict.keys():
						distmean = 1000.0/self.priordict['Para'][0]
						parashift = self.priordict['Para'][0]-3.0*self.priordict['Para'][1]
						distsig = (1000.0/parashift)-distmean
						initsample_v_i.append(distsig*np.random.randn()+distmean)
					else:
						initsample_v_i.append(self.distran*np.random.rand()+self.mindist)
					initsample_v_i.append(self.Avran*np.random.rand()+self.minAv)
				initsample_u_i = self.prior_inversetrans(initsample_v_i)

				initsample_v[i,:] = initsample_v_i
				initsample_u[i,:] = initsample_u_i

		else:
			restart_from = Table.read(restart,format='ascii')
			if len(restart_from) > npoints:
				if weightrestart:
					restart_ind = np.random.choice(range(0,len(restart_from)),npoints,replace=False,p=np.exp(restart_from['logwt']-restart_from['logz'][-1]))					
				else:
					restart_ind = np.random.choice(range(0,len(restart_from)),npoints,replace=False)					
				restart_sel = restart_from[restart_ind]
				addind = np.random.choice(len(self.MODPARS),int(0.25*npoints),replace=False)
				addsel = self.MODPARS[addind]
			else:
				restart_sel = restart_from
				numbadd = 1.25*npoints-len(restart_sel)
				addind = np.random.choice(len(self.MODPARS),numbadd,replace=False)
				addsel = self.MODPARS[addind]

			initsample_v = np.empty((len(restart_sel)+len(addsel),self.ndim), dtype=np.float64)
			initsample_u = np.empty((len(restart_sel)+len(addsel),self.ndim), dtype=np.float64)

			for i in range(len(restart_sel)):
				initsample_v_i = [float(restart_sel['EEP'][i]),float(restart_sel['Age'][i]),float(restart_sel['[Fe/H]in'][i])]
				if self.fitphotbool:
					initsample_v_i.append(float(restart_sel['Dist'][i]))
					initsample_v_i.append(float(restart_sel['Av'][i]))
				initsample_u_i = self.prior_inversetrans(initsample_v_i)

				initsample_v[i,:] = initsample_v_i
				initsample_u[i,:] = initsample_u_i

			for i in range(len(addsel)):
				initsample_v_i = [float(addsel['EEP'][i]),10.0**(float(addsel['log_age'][i])-9.0),float(addsel['[Fe/H]in'][i])]
				if self.fitphotbool:
					# initsample_v_i.append(self.distran*np.random.rand()+self.mindist)
					# initsample_v_i.append(self.Avran*np.random.rand()+self.minAv)
					distmean = 1000.0/self.priordict['Para'][0]
					parashift = self.priordict['Para'][0]-3.0*self.priordict['Para'][1]
					distsig = (1000.0/parashift)-distmean
					initsample_v_i.append(distsig*np.random.randn()+distmean)
					initsample_v_i.append(self.Avran*np.random.rand()+self.minAv)
				initsample_u_i = self.prior_inversetrans(initsample_v_i)

				initsample_v[i+len(restart_sel),:] = initsample_v_i
				initsample_u[i+len(restart_sel),:] = initsample_u_i


		print 'Start Nestle w/ {0} number of samples'.format(len(initsample_v))
		self.startmct = datetime.now()
		self.stept = datetime.now()
		self.ncallt = 0
		self.maxcallnum = 0
		sys.stdout.flush()
		result = nestle.sample(
			self.lnp_call_nestle,self.prior_trans,self.ndim,method=samplertype,
			npoints=len(initsample_v),callback=self.nestle_callback,user_sample=initsample_u,
			# dlogz=1.0,
			# update_interval=1,
			maxrejcall=maxrejcall,
			)
		p,cov = nestle.mean_and_cov(result.samples,result.weights)
		return result,p,cov
Exemplo n.º 41
0
    t = 2.0 * tmax * x - tmax
    return (2.0 + np.cos(t[0]/2.0)*np.cos(t[1]/2.0))**5.0

def prior(x):
    return x

# plot the surface
plt.figure(figsize=(8., 8.))
ax = plt.axes(aspect=1)
xx, yy = np.meshgrid(np.linspace(0., 1., 50),
                     np.linspace(0., 1., 50))
Z = loglike(np.array([xx, yy]))
ax.contourf(xx, yy, Z, 12, cmap=plt.cm.Blues_r)
plt.title("True Log likelihood surface")

###############################################################################
# Run nested sampling in multi-ellipsoid mode and print a summary of results:

res = nestle.sample(loglike, prior, 2, npoints=200, method='multi',
                    update_interval=20)
print(res.summary())

###############################################################################
# Plot the samples. Note that this represents the *likelihood* rather than
# its log, hence it is much more highly peaked.

fig = corner.corner(res.samples, weights=res.weights, bins=500,
                    range=[(0., 1.), (0., 1.)])
fig.set_size_inches(8., 8.)

Exemplo n.º 42
0
yerr = 0.1+0.5*np.random.rand(N)
y += yerr * np.random.randn(N)


# The likelihood function:
def loglike(theta):
    return -0.5*(np.sum((y-model(theta, x))**2/yerr**2))


# Defines a flat prior in 0 < m < 1, 0 < b < 100:
def prior_transform(theta):
    return np.array([1., 100.]) * theta


# Run nested sampling
res = nestle.sample(loglike, prior_transform, 2, method='single',
                    npoints=1000)
print(res.summary())

# weighted average and covariance:
p, cov = nestle.mean_and_cov(res.samples, res.weights)

print("m = {0:5.2f} +/- {1:5.2f}".format(p[0], np.sqrt(cov[0, 0])))
print("b = {0:5.2f} +/- {1:5.2f}".format(p[1], np.sqrt(cov[1, 1])))

plt.figure()
plt.errorbar(x, y, yerr=yerr, capsize=0, fmt='k.', ecolor='.7')
plt.plot([0., 10.], model(p, np.array([0., 10.])), c='k')
plt.show()

###############################################################################
# Plot samples to see the full posterior surface.
Exemplo n.º 43
0
def run_nestle(**config):
    ndim = config['ndim']

    def priortransform(u):
        assert len(u) == ndim, u
        return u

    def dump_callback(info):
        sys.stderr.write("\r%d|%d|logz=%.4f|eff=%f%%    " %
                         (info['it'], info['ncall'], info['logz'],
                          info['it'] * 100. / info['ncall']))

        #if info['it'] % 50 != 0: return
        #print "Replacements: %d" % (info['ncall'])
        #print "Samples: %d" % (info['it'])
        #print "Efficiency: %f" % (info['ncall']/info['it'])
        #print "Nested Sampling ln(Z): %f" % (info['logz'])

    if 'seed' in config:
        numpy.random.seed(config['seed'])

    # can use directly
    loglikelihood = config['loglikelihood']
    nlive_points = config['nlive_points']
    method = config['method']
    if config.get('unlimited_sampling', False):
        max_samples = None
    else:
        max_samples = 2000000
    print()
    print('running nestle ...')
    options = dict()
    #if 'enlarge' in config:
    #	options['enlarge'] = config['enlarge']
    starttime = time.time()
    result = nestle.sample(loglikelihood=loglikelihood,
                           prior_transform=priortransform,
                           ndim=ndim,
                           npoints=nlive_points,
                           method=method,
                           update_interval=None,
                           maxcall=max_samples,
                           dlogz=0.5,
                           rstate=numpy.random,
                           callback=dump_callback,
                           **options)
    endtime = time.time()
    output_basename = config['output_basename']
    print()
    print('nestle done lnZ = %(logz).1f +- %(logzerr).1f' % (result))

    if config.get('seed', 0) == 0:
        import matplotlib.pyplot as plt
        x = result['samples']
        y = exp(result['logl'])
        plt.plot(x[:, 0], y, 'x', color='blue', ms=1)
        plt.savefig(output_basename + 'nested_samples.pdf',
                    bbox_inches='tight')
        plt.close()

        L = result['logl']
        width = result['weights']
        plt.plot(width,
                 L,
                 'x-',
                 color='blue',
                 ms=1,
                 label='Z=%.2f (%.2f)' %
                 (result['logz'], log(exp(L + width).sum())))
        fromleft = exp(L + width)[::-1].cumsum()
        fromleft /= fromleft.max()
        mask = (fromleft < 0.99)[::-1]
        if mask.any():
            i = width[mask].argmax()
            plt.ylim(L.max() - log(1000), L.max())
            plt.fill_between(width[mask],
                             L[mask],
                             L.max() - log(1000),
                             color='grey',
                             alpha=0.3)
        plt.xlabel('prior mass')
        plt.ylabel('likelihood')
        plt.legend(loc='best')
        plt.savefig(output_basename + 'nested_integral.pdf',
                    bbox_inches='tight')
        plt.close()

        #posterioru, posteriorx = equal_weighted_posterior(result['weights'])
        #plt.figure(figsize=(ndim*2, ndim*2))
        #marginal_plots(weights=result['weights'], ndim=ndim)
        #plt.savefig(output_basename + 'posterior.pdf', bbox_inches='tight')
        #plt.close()

    return dict(
        Z_computed=float(result['logz']),
        Z_computed_err=float(result['logzerr']),
        niterations=result['niter'],
        duration=endtime - starttime,
    )
Exemplo n.º 44
0
def nest_lc(data,
            model,
            vparam_names,
            bounds,
            guess_amplitude_bound=False,
            minsnr=5.,
            priors=None,
            ppfs=None,
            npoints=100,
            method='single',
            maxiter=None,
            maxcall=None,
            modelcov=False,
            rstate=None,
            verbose=False,
            warn=True,
            **kwargs):
    """Run nested sampling algorithm to estimate model parameters and evidence.

    Parameters
    ----------
    data : `~astropy.table.Table` or `~numpy.ndarray` or `dict`
        Table of photometric data. Must include certain columns.
        See the "Photometric Data" section of the documentation for
        required columns.
    model : `~sncosmo.Model`
        The model to fit.
    vparam_names : list
        Model parameters to vary in the fit.
    bounds : `dict`
        Bounded range for each parameter. Bounds must be given for
        each parameter, with the exception of ``t0``: by default, the
        minimum bound is such that the latest phase of the model lines
        up with the earliest data point and the maximum bound is such
        that the earliest phase of the model lines up with the latest
        data point.
    guess_amplitude_bound : bool, optional
        If true, bounds for the model's amplitude parameter are determined
        automatically based on the data and do not need to be included in
        `bounds`. The lower limit is set to zero and the upper limit is 10
        times the amplitude "guess" (which is based on the highest-flux
        data point in any band). Default is False.
    minsnr : float, optional
        Minimum signal-to-noise ratio of data points to use when guessing
        amplitude bound. Default is 5.
    priors : `dict`, optional
        Prior probability distribution function for each parameter. The keys
        should be parameter names and the values should be callables that
        accept a float. If a parameter is not in the dictionary, the prior
        defaults to a flat distribution between the bounds.
    ppfs : `dict`, optional
        Prior percent point function (inverse of the cumulative distribution
        function) for each parameter. If a parameter is in this dictionary,
        the ppf takes precedence over a prior pdf specified in ``priors``.
    npoints : int, optional
        Number of active samples to use. Increasing this value increases
        the accuracy (due to denser sampling) and also the time
        to solution.
    method : {'classic', 'single', 'multi'}, optional
        Method used to select new points. Choices are 'classic',
        single-ellipsoidal ('single'), multi-ellipsoidal ('multi'). Default
        is 'single'.
    maxiter : int, optional
        Maximum number of iterations. Iteration may stop earlier if
        termination condition is reached. Default is no limit.
    maxcall : int, optional
        Maximum number of likelihood evaluations. Iteration may stop earlier
        if termination condition is reached. Default is no limit.
    modelcov : bool, optional
        Include model covariance when calculating chisq. Default is False.
    rstate : `~numpy.random.RandomState`, optional
        RandomState instance. If not given, the global random state of the
        ``numpy.random`` module will be used.
    verbose : bool, optional
        Print running evidence sum on a single line.
    warn : bool, optional
        Issue warning when dropping bands outside the model range. Default is
        True.

        *New in version 1.5.0*

    Returns
    -------
    res : Result
        Attributes are:

        * ``niter``: total number of iterations
        * ``ncall``: total number of likelihood function calls
        * ``time``: time in seconds spent in iteration loop.
        * ``logz``: natural log of the Bayesian evidence Z.
        * ``logzerr``: estimate of uncertainty in logz (due to finite sampling)
        * ``h``: Bayesian information.
        * ``vparam_names``: list of parameter names varied.
        * ``samples``: 2-d `~numpy.ndarray`, shape is (nsamples, nparameters).
          Each row is the parameter values for a single sample. For example,
          ``samples[0, :]`` is the parameter values for the first sample.
        * ``logprior``: 1-d `~numpy.ndarray` (length=nsamples);
          log(prior volume) for each sample.
        * ``logl``: 1-d `~numpy.ndarray` (length=nsamples); log(likelihood)
          for each sample.
        * ``weights``: 1-d `~numpy.ndarray` (length=nsamples);
          Weight corresponding to each sample. The weight is proportional to
          the prior * likelihood for the sample.
        * ``parameters``: 1-d `~numpy.ndarray` of weighted-mean parameter
          values from samples (including fixed parameters). Order corresponds
          to ``model.param_names``.
        * ``covariance``: 2-d `~numpy.ndarray` of parameter covariance;
          indicies correspond to order of ``vparam_names``. Calculated from
          ``samples`` and ``weights``.
        * ``errors``: OrderedDict of varied parameter uncertainties.
          Corresponds to square root of diagonal entries in covariance matrix.
        * ``ndof``: Number of degrees of freedom (len(data) -
          len(vparam_names)).
        * ``bounds``: Dictionary of bounds on varied parameters (including
          any automatically determined bounds).
        * ``data_mask``: Boolean array the same length as data specifying
          whether each observation was used.
          *New in version 1.5.0.*

    estimated_model : `~sncosmo.Model`
        A copy of the model with parameters set to the values in
        ``res.parameters``.
    """

    try:
        import nestle
    except ImportError:
        raise ImportError("nest_lc() requires the nestle package.")

    # warnings
    if "nobj" in kwargs:
        warnings.warn("The nobj keyword is deprecated and will be removed in "
                      "sncosmo v2.0. Use `npoints` instead.")
        npoints = kwargs.pop("nobj")

    # experimental parameters
    tied = kwargs.get("tied", None)

    data = photometric_data(data)

    # sort by time
    if not np.all(np.ediff1d(data.time) >= 0.0):
        sortidx = np.argsort(data.time)
        data = data[sortidx]
    else:
        sortidx = None

    model = copy.copy(model)
    bounds = copy.copy(bounds)  # need to copy this b/c we modify it below

    # Order vparam_names the same way it is ordered in the model:
    vparam_names = [s for s in model.param_names if s in vparam_names]

    # Drop data that the model doesn't cover.
    fitdata, data_mask = cut_bands(data,
                                   model,
                                   z_bounds=bounds.get('z', None),
                                   warn=warn)

    if guess_amplitude_bound:
        if model.param_names[2] not in vparam_names:
            raise ValueError("Amplitude bounds guessing enabled but "
                             "amplitude parameter {0!r} is not varied".format(
                                 model.param_names[2]))
        if model.param_names[2] in bounds:
            raise ValueError("cannot supply bounds for parameter {0!r}"
                             " when guess_amplitude_bound=True".format(
                                 model.param_names[2]))

        # If redshift is bounded, set model redshift to midpoint of bounds
        # when doing the guess.
        if 'z' in bounds:
            model.set(z=sum(bounds['z']) / 2.)
        _, amplitude = guess_t0_and_amplitude(fitdata, model, minsnr)
        bounds[model.param_names[2]] = (0., 10. * amplitude)

    # Find t0 bounds to use, if not explicitly given
    if 't0' in vparam_names and 't0' not in bounds:
        bounds['t0'] = t0_bounds(fitdata, model)

    if ppfs is None:
        ppfs = {}
    if tied is None:
        tied = {}

    # Convert bounds/priors combinations into ppfs
    if bounds is not None:
        for key, val in six.iteritems(bounds):
            if key in ppfs:
                continue  # ppfs take priority over bounds/priors
            a, b = val
            if priors is not None and key in priors:
                # solve ppf at discrete points and return interpolating
                # function
                x_samples = np.linspace(0., 1., 101)
                ppf_samples = ppf(priors[key], x_samples, a, b)
                f = Interp1D(0., 1., ppf_samples)
            else:
                f = Interp1D(0., 1., np.array([a, b]))
            ppfs[key] = f

    # NOTE: It is important that iparam_names is in the same order
    # every time, otherwise results will not be reproducible, even
    # with same random seed.  This is because iparam_names[i] is
    # matched to u[i] below and u will be in a reproducible order,
    # so iparam_names must also be.
    iparam_names = [key for key in vparam_names if key in ppfs]
    ppflist = [ppfs[key] for key in iparam_names]
    npdim = len(iparam_names)  # length of u
    ndim = len(vparam_names)  # length of v

    # Check that all param_names either have a direct prior or are tied.
    for name in vparam_names:
        if name in iparam_names:
            continue
        if name in tied:
            continue
        raise ValueError(
            "Must supply ppf or bounds or tied for parameter '{}'".format(
                name))

    def prior_transform(u):
        d = {}
        for i in range(npdim):
            d[iparam_names[i]] = ppflist[i](u[i])
        v = np.empty(ndim, dtype=np.float)
        for i in range(ndim):
            key = vparam_names[i]
            if key in d:
                v[i] = d[key]
            else:
                v[i] = tied[key](d)
        return v

    # Indicies of the model parameters in vparam_names
    idx = np.array([model.param_names.index(name) for name in vparam_names])

    def loglike(parameters):
        model.parameters[idx] = parameters
        return -0.5 * chisq(fitdata, model, modelcov=modelcov)

    t0 = time.time()
    res = nestle.sample(loglike,
                        prior_transform,
                        ndim,
                        npdim=npdim,
                        npoints=npoints,
                        method=method,
                        maxiter=maxiter,
                        maxcall=maxcall,
                        rstate=rstate,
                        callback=(nestle.print_progress if verbose else None))
    elapsed = time.time() - t0

    # estimate parameters and covariance from samples
    vparameters, cov = nestle.mean_and_cov(res.samples, res.weights)

    # update model parameters to estimated ones.
    model.set(**dict(zip(vparam_names, vparameters)))

    # If we need to, unsort the mask so mask applies to input data
    if sortidx is not None:
        unsort_idx = np.argsort(sortidx)  # indicies that will unsort array
        data_mask = data_mask[unsort_idx]

    # `res` is a nestle.Result object. Collect result into a sncosmo.Result
    # object for consistency, and add more fields.
    res = Result(
        niter=res.niter,
        ncall=res.ncall,
        logz=res.logz,
        logzerr=res.logzerr,
        h=res.h,
        samples=res.samples,
        weights=res.weights,
        logvol=res.logvol,
        logl=res.logl,
        vparam_names=copy.copy(vparam_names),
        ndof=len(fitdata) - len(vparam_names),
        bounds=bounds,
        time=elapsed,
        parameters=model.parameters.copy(),
        covariance=cov,
        errors=OrderedDict(zip(vparam_names, np.sqrt(np.diagonal(cov)))),
        param_dict=OrderedDict(zip(model.param_names, model.parameters)),
        data_mask=data_mask)

    # Deprecated result fields.
    depmsg = ("The `param_names` attribute is deprecated in sncosmo v1.0 "
              "and will be removed in sncosmo v2.0."
              "Use `vparam_names` instead.")
    res.__dict__['deprecated']['param_names'] = (res.vparam_names, depmsg)

    depmsg = ("The `logprior` attribute is deprecated in sncosmo v1.2 "
              "and will be changed in sncosmo v2.0."
              "Use `logvol` instead.")
    res.__dict__['deprecated']['logprior'] = (res.logvol, depmsg)

    return res, model