Source code for lenstronomy.Sampling.Samplers.dynesty_sampler

__author__ = 'aymgal'

import numpy as np

from lenstronomy.Sampling.Samplers.base_nested_sampler import NestedSampler
import lenstronomy.Util.sampling_util as utils

__all__ = ['DynestySampler']


[docs]class DynestySampler(NestedSampler): """ Wrapper for dynamical nested sampling algorithm Dynesty by J. Speagle paper : https://arxiv.org/abs/1904.02180 doc : https://dynesty.readthedocs.io/ """ def __init__(self, likelihood_module, prior_type='uniform', prior_means=None, prior_sigmas=None, width_scale=1, sigma_scale=1, bound='multi', sample='auto', use_mpi=False, use_pool=None): """ :param likelihood_module: likelihood_module like in likelihood.py (should be callable) :param prior_type: 'uniform' of 'gaussian', for converting the unit hypercube to param cube :param prior_means: if prior_type is 'gaussian', mean for each param :param prior_sigmas: if prior_type is 'gaussian', std dev for each param :param width_scale: scale the widths of the parameters space by this factor :param sigma_scale: if prior_type is 'gaussian', scale the gaussian sigma by this factor :param bound: specific to Dynesty, see https://dynesty.readthedocs.io :param sample: specific to Dynesty, see https://dynesty.readthedocs.io :param use_mpi: Use MPI computing if `True` :param use_pool: specific to Dynesty, see https://dynesty.readthedocs.io """ self._check_install() super(DynestySampler, self).__init__(likelihood_module, prior_type, prior_means, prior_sigmas, width_scale, sigma_scale) # create the Dynesty sampler if use_mpi: from schwimmbad import MPIPool import sys pool = MPIPool(use_dill=True) # use_dill=True not supported for some versions of schwimmbad if not pool.is_master(): pool.wait() sys.exit(0) self._sampler = self._dynesty.DynamicNestedSampler(self.log_likelihood, self.prior, self.n_dims, bound=bound, sample=sample, pool=pool, use_pool=use_pool) else: self._sampler = self._dynesty.DynamicNestedSampler(self.log_likelihood, self.prior, self.n_dims, bound=bound, sample=sample) self._has_warned = False
[docs] def prior(self, u): """ compute the mapping between the unit cube and parameter cube :param u: unit hypercube, sampled by the algorithm :return: hypercube in parameter space """ if self.prior_type == 'gaussian': p = utils.cube2args_gaussian(u, self.lowers, self.uppers, self.means, self.sigmas, self.n_dims, copy=True) elif self.prior_type == 'uniform': p = utils.cube2args_uniform(u, self.lowers, self.uppers, self.n_dims, copy=True) else: raise ValueError('prior type %s not supported! Chose "gaussian" or "uniform".') return p
[docs] def log_likelihood(self, x): """ compute the log-likelihood given list of parameters :param x: parameter values :return: log-likelihood (from the likelihood module) """ log_l = self._ll(x) if not np.isfinite(log_l): if not self._has_warned: print("WARNING : logL is not finite : return very low value instead") log_l = -1e15 self._has_warned = True return float(log_l)
[docs] def run(self, kwargs_run): """ run the Dynesty nested sampler see https://dynesty.readthedocs.io for content of kwargs_run :param kwargs_run: kwargs directly passed to DynamicNestedSampler.run_nested :return: samples, means, logZ, logZ_err, logL, results """ print("prior type :", self.prior_type) print("parameter names :", self.param_names) self._sampler.run_nested(**kwargs_run) results = self._sampler.results samples_w = results.samples # weighted samples log_l = results.logl log_z = results.logz log_z_err = results.logzerr # Compute weighted mean and covariance. weights = np.exp(results.logwt - log_z[-1]) # normalized weights if np.sum(weights) != 1.: # TODO : clearly this is not optimal... # weights should by definition be normalized, but it appears that for very small # number of live points (typically in test routines), # it is not *quite* the case (up to 6 decimals) weights = weights / np.sum(weights) means, covs = self._dyfunc.mean_and_cov(samples_w, weights) # Resample weighted samples to get equally weighted (aka unweighted) samples samples = self._dyfunc.resample_equal(samples_w, weights) return samples, means, log_z, log_z_err, log_l, results
def _check_install(self): try: import dynesty import dynesty.utils as dyfunc except ImportError: print("Warning : dynesty not properly installed (results might be unexpected). \ You can get it with $pip install dynesty.") self._dynesty_installed = False else: self._dynesty_installed = True self._dynesty = dynesty self._dyfunc = dyfunc