From 410eb05bff9c535a626f5738418e71e6b10d651c Mon Sep 17 00:00:00 2001 From: Michael Williams <michael.williams@ligo.org> Date: Tue, 18 Jan 2022 15:07:18 +0000 Subject: [PATCH] Resolve "Conversion function not applied to posterior" --- bilby/core/sampler/cpnest.py | 8 +- bilby/core/sampler/nessai.py | 9 +- bilby/core/sampler/pymc3.py | 22 ++--- test/integration/sampler_run_test.py | 120 ++++++++++++++++++++------- 4 files changed, 104 insertions(+), 55 deletions(-) diff --git a/bilby/core/sampler/cpnest.py b/bilby/core/sampler/cpnest.py index 7a089a4ca..e64365f2e 100644 --- a/bilby/core/sampler/cpnest.py +++ b/bilby/core/sampler/cpnest.py @@ -3,6 +3,7 @@ import array import copy import numpy as np +from numpy.lib.recfunctions import structured_to_unstructured from pandas import DataFrame from .base_sampler import NestedSampler @@ -121,11 +122,12 @@ class Cpnest(NestedSampler): out.plot() self.calc_likelihood_count() - self.result.posterior = DataFrame(out.posterior_samples) + self.result.samples = structured_to_unstructured( + out.posterior_samples[self.search_parameter_keys] + ) + self.result.log_likelihood_evaluations = out.posterior_samples['logL'] self.result.nested_samples = DataFrame(out.get_nested_samples(filename='')) self.result.nested_samples.rename(columns=dict(logL='log_likelihood'), inplace=True) - self.result.posterior.rename(columns=dict(logL='log_likelihood', logPrior='log_prior'), - inplace=True) _, log_weights = compute_weights(np.array(self.result.nested_samples.log_likelihood), np.array(out.NS.state.nlive)) self.result.nested_samples['weights'] = np.exp(log_weights) diff --git a/bilby/core/sampler/nessai.py b/bilby/core/sampler/nessai.py index 5e3ef364b..d8bb578a4 100644 --- a/bilby/core/sampler/nessai.py +++ b/bilby/core/sampler/nessai.py @@ -70,7 +70,7 @@ class Nessai(NestedSampler): def run_sampler(self): from nessai.flowsampler import FlowSampler from nessai.model import Model as BaseModel - from nessai.livepoint import dict_to_live_points + from nessai.livepoint import dict_to_live_points, live_points_to_array from nessai.posterior import compute_weights from nessai.utils import setup_logger @@ -136,12 +136,13 @@ class Nessai(NestedSampler): # Manually set likelihood evaluations because parallelisation breaks the counter self.result.num_likelihood_evaluations = out.ns.likelihood_evaluations[-1] - self.result.posterior = DataFrame(out.posterior_samples) + self.result.samples = live_points_to_array( + out.posterior_samples, self.search_parameter_keys + ) + self.result.log_likelihood_evaluations = out.posterior_samples['logL'] self.result.nested_samples = DataFrame(out.nested_samples) self.result.nested_samples.rename( columns=dict(logL='log_likelihood', logP='log_prior'), inplace=True) - self.result.posterior.rename( - columns=dict(logL='log_likelihood', logP='log_prior'), inplace=True) _, log_weights = compute_weights(np.array(self.result.nested_samples.log_likelihood), np.array(out.ns.state.nlive)) self.result.nested_samples['weights'] = np.exp(log_weights) diff --git a/bilby/core/sampler/pymc3.py b/bilby/core/sampler/pymc3.py index c5c0a0d18..25522f82f 100644 --- a/bilby/core/sampler/pymc3.py +++ b/bilby/core/sampler/pymc3.py @@ -551,23 +551,13 @@ class Pymc3(MCMCSampler): with self.pymc3_model: # perform the sampling - trace = pymc3.sample(**self.kwargs) + trace = pymc3.sample(**self.kwargs, return_inferencedata=True) - nparams = len([key for key in self.priors.keys() if not isinstance(self.priors[key], DeltaFunction)]) - nsamples = len(trace) * self.chains - - self.result.samples = np.zeros((nsamples, nparams)) - count = 0 - for key in self.priors.keys(): - if not isinstance(self.priors[key], DeltaFunction): # ignore DeltaFunction variables - if not isinstance(self.priors[key], MultivariateGaussian): - self.result.samples[:, count] = trace[key] - else: - # get multivariate Gaussian samples - priorset = self.multivariate_normal_sets[key]['set'] - index = self.multivariate_normal_sets[key]['index'] - self.result.samples[:, count] = trace[priorset][:, index] - count += 1 + posterior = trace.posterior.to_dataframe().reset_index() + self.result.samples = posterior[self.search_parameter_keys] + self.result.log_likelihood_evaluations = np.sum( + trace.log_likelihood.likelihood.values, axis=-1 + ).flatten() self.result.sampler_output = np.nan self.calculate_autocorrelation(self.result.samples) self.result.log_evidence = np.nan diff --git a/test/integration/sampler_run_test.py b/test/integration/sampler_run_test.py index c72ca91b7..e89336edc 100644 --- a/test/integration/sampler_run_test.py +++ b/test/integration/sampler_run_test.py @@ -25,8 +25,19 @@ class TestRunningSamplers(unittest.TestCase): self.priors = bilby.core.prior.PriorDict() self.priors["m"] = bilby.core.prior.Uniform(0, 5, boundary="periodic") self.priors["c"] = bilby.core.prior.Uniform(-2, 2, boundary="reflective") + self.kwargs = dict( + save=False, + conversion_function=self.conversion_function, + ) bilby.core.utils.check_directory_exists_and_if_not_mkdir("outdir") + @staticmethod + def conversion_function(parameters, likelihood, prior): + converted = parameters.copy() + if 'derived' not in converted: + converted['derived'] = converted['m'] * converted['c'] + return converted + def tearDown(self): del self.likelihood del self.priors @@ -34,17 +45,21 @@ class TestRunningSamplers(unittest.TestCase): shutil.rmtree("outdir") def test_run_cpnest(self): - _ = bilby.run_sampler( + pytest.importorskip("cpnest") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="cpnest", nlive=100, - save=False, resume=False, + **self.kwargs ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_dnest4(self): - _ = bilby.run_sampler( + pytest.importorskip("dnest4") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="dnest4", @@ -54,20 +69,26 @@ class TestRunningSamplers(unittest.TestCase): num_per_step=10, thread_steps=1, num_particles=50, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_dynesty(self): - _ = bilby.run_sampler( + pytest.importorskip("dynesty") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="dynesty", nlive=100, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_dynamic_dynesty(self): - _ = bilby.run_sampler( + pytest.importorskip("dynesty") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="dynamic_dynesty", @@ -77,62 +98,79 @@ class TestRunningSamplers(unittest.TestCase): maxbatch=0, maxcall=100, bound="single", - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_emcee(self): - _ = bilby.run_sampler( + pytest.importorskip("emcee") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="emcee", iterations=1000, nwalkers=10, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_kombine(self): - _ = bilby.run_sampler( + pytest.importorskip("kombine") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="kombine", iterations=2000, nwalkers=20, - save=False, autoburnin=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_nestle(self): - _ = bilby.run_sampler( + pytest.importorskip("nestle") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="nestle", nlive=100, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_nessai(self): - _ = bilby.run_sampler( + pytest.importorskip("nessai") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="nessai", nlive=100, poolsize=1000, max_iteration=1000, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_pypolychord(self): pytest.importorskip("pypolychord") - _ = bilby.run_sampler( + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="pypolychord", nlive=100, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_ptemcee(self): - _ = bilby.run_sampler( + pytest.importorskip("ptemcee") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="ptemcee", @@ -141,60 +179,78 @@ class TestRunningSamplers(unittest.TestCase): burn_in_act=1, ntemps=1, frac_threshold=0.5, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None @pytest.mark.skipif(sys.version_info[1] <= 6, reason="pymc3 is broken in py36") def test_run_pymc3(self): - _ = bilby.run_sampler( + pytest.importorskip("pymc3") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="pymc3", draws=50, tune=50, n_init=250, - save=False, + **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_pymultinest(self): - _ = bilby.run_sampler( + pytest.importorskip("pymultinest") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="pymultinest", nlive=100, - save=False, + **self.kwargs ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_PTMCMCSampler(self): - _ = bilby.run_sampler( + pytest.importorskip("PTMCMCSampler") + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, sampler="PTMCMCsampler", Niter=101, burn=2, isave=100, - save=False, + **self.kwargs ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_ultranest(self): + pytest.importorskip("ultranest") # run using NestedSampler (with nlive specified) - _ = bilby.run_sampler( + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, - sampler="ultranest", nlive=100, save=False, + sampler="ultranest", nlive=100, **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None # run using ReactiveNestedSampler (with no nlive given) - _ = bilby.run_sampler( + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, - sampler='ultranest', save=False, + sampler='ultranest', **self.kwargs, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None def test_run_bilby_mcmc(self): - _ = bilby.run_sampler( + res = bilby.run_sampler( likelihood=self.likelihood, priors=self.priors, - sampler="bilby_mcmc", nsamples=200, save=False, + sampler="bilby_mcmc", nsamples=200, **self.kwargs, printdt=1, ) + assert 'derived' in res.posterior + assert res.log_likelihood_evaluations is not None if __name__ == "__main__": -- GitLab