Skip to content
Snippets Groups Projects
Commit 54105163 authored by Moritz Huebner's avatar Moritz Huebner
Browse files

Resolve "Follow-up from "Adding dnest4 Sampler""

parent cd443619
No related branches found
No related tags found
No related merge requests found
......@@ -25,11 +25,11 @@ from .dnest4 import DNest4
from . import proposal
IMPLEMENTED_SAMPLERS = {
'cpnest': Cpnest, 'dynamic_dynesty': DynamicDynesty, 'dynesty': Dynesty,
'emcee': Emcee, 'kombine': Kombine, 'nestle': Nestle, 'ptemcee': Ptemcee,
'ptmcmcsampler': PTMCMCSampler, 'pymc3': Pymc3, 'pymultinest': Pymultinest,
'pypolychord': PyPolyChord, 'ultranest': Ultranest,
'fake_sampler': FakeSampler, 'dnest4': DNest4}
'cpnest': Cpnest, 'dnest4': DNest4, 'dynamic_dynesty': DynamicDynesty,
'dynesty': Dynesty, 'emcee': Emcee, 'kombine': Kombine, 'nestle': Nestle,
'ptemcee': Ptemcee, 'ptmcmcsampler': PTMCMCSampler, 'pymc3': Pymc3,
'pymultinest': Pymultinest, 'pypolychord': PyPolyChord, 'ultranest': Ultranest,
'fake_sampler': FakeSampler}
if command_line_args.sampler_help:
sampler = command_line_args.sampler_help
......
from __future__ import absolute_import
import datetime
import distutils.dir_util
import numpy as np
import os
import tempfile
from pandas import DataFrame
from ..utils import logger, command_line_args, Counter
from ..utils import logger, check_directory_exists_and_if_not_mkdir, command_line_args, Counter
from ..prior import Prior, PriorDict, DeltaFunction, Constraint
from ..result import Result, read_in_result
......@@ -541,7 +544,8 @@ class Sampler(object):
class NestedSampler(Sampler):
npoints_equiv_kwargs = ['nlive', 'nlives', 'n_live_points', 'npoints', 'npoint', 'Nlive', 'num_live_points']
npoints_equiv_kwargs = ['nlive', 'nlives', 'n_live_points', 'npoints',
'npoint', 'Nlive', 'num_live_points', 'num_particles']
walks_equiv_kwargs = ['walks', 'steps', 'nmcmc']
def reorder_loglikelihoods(self, unsorted_loglikelihoods, unsorted_samples,
......@@ -601,6 +605,27 @@ class NestedSampler(Sampler):
else:
return np.nan_to_num(-np.inf)
def _setup_run_directory(self):
"""
If using a temporary directory, the output directory is moved to the
temporary directory.
Used for Dnest4, Pymultinest, and Ultranest.
"""
if self.use_temporary_directory:
temporary_outputfiles_basename = tempfile.TemporaryDirectory().name
self.temporary_outputfiles_basename = temporary_outputfiles_basename
if os.path.exists(self.outputfiles_basename):
distutils.dir_util.copy_tree(self.outputfiles_basename, self.temporary_outputfiles_basename)
check_directory_exists_and_if_not_mkdir(temporary_outputfiles_basename)
self.kwargs["outputfiles_basename"] = self.temporary_outputfiles_basename
logger.info("Using temporary file {}".format(temporary_outputfiles_basename))
else:
check_directory_exists_and_if_not_mkdir(self.outputfiles_basename)
self.kwargs["outputfiles_basename"] = self.outputfiles_basename
logger.info("Using output file {}".format(self.outputfiles_basename))
class MCMCSampler(Sampler):
nwalkers_equiv_kwargs = ['nwalker', 'nwalkers', 'draws', 'Niter']
......
from __future__ import absolute_import
import os
import tempfile
import shutil
import distutils.dir_util
import signal
import time
import datetime
import sys
import numpy as np
import pandas as pd
......@@ -20,14 +18,14 @@ class _DNest4Model(object):
def __init__(self, log_likelihood_func, from_prior_func, widths, centers, highs, lows):
"""Initialize the DNest4 model.
Args:
log_likelihood_func (function): The loglikelihood function to use
during the Nested Sampling run.
from_prior_func (function): The function to use when randomly
selecting parameter vectors from the prior space.
widths (numpy.array): The approximate widths of the prior
distrbutions.
centers (numpy.array): The approximate center points of the prior
distributions.
log_likelihood_func: function
The loglikelihood function to use during the Nested Sampling run.
from_prior_func: function
The function to use when randomly selecting parameter vectors from the prior space.
widths: array_like
The approximate widths of the prior distrbutions.
centers: array_like
The approximate center points of the prior distributions.
"""
self._log_likelihood = log_likelihood_func
self._from_prior = from_prior_func
......@@ -58,9 +56,11 @@ class _DNest4Model(object):
return 0.0
def wrap(self, x, a, b):
assert b > a
return (x - a) % (b - a) + a
@staticmethod
def wrap(x, minimum, maximum):
if maximum <= minimum:
raise ValueError("maximum {} <= minimum {}, when trying to wrap coordinates".format(maximum, minimum))
return (x - minimum) % (maximum - minimum) + minimum
class DNest4(NestedSampler):
......@@ -83,8 +83,9 @@ class DNest4(NestedSampler):
The python DNest4 backend for storing the output.
Options are: 'memory' and 'csv'. If 'memory' the
DNest4 outputs are stored in memory during the run. If 'csv' the
DNest4 outputs are written out to filse with a CSV format during
DNest4 outputs are written out to files with a CSV format during
the run.
CSV backend may not be functional right now (October 2020)
num_steps: int
The number of MCMC iterations to run
new_level_interval: int
......@@ -97,53 +98,20 @@ class DNest4(NestedSampler):
Set the seed for the C++ random number generator
verbose: Bool
If True, prints information during run
TO DO: add equivalent args for num_particles (nlive, etc.)
Add sampling time functions
"""
default_kwargs = dict(
max_num_levels=20,
num_steps=500, # Number of iterations
new_level_interval=10000,
num_per_step=10000,
thread_steps=1,
num_particles=1000,
lam=10.0,
beta=100,
seed=None,
verbose=True,
outputfiles_basename=None,
# backend_callback=None, # for checkpointing in dnest5
backend='memory', # csv is currently bugged right now
# could change max_num_levels based on snr
)
def __init__(
self,
likelihood,
priors,
outdir="outdir",
label="label",
use_ratio=False,
plot=False,
exit_code=77,
skip_import_verification=False,
temporary_directory=True,
resume=True,
**kwargs
):
default_kwargs = dict(max_num_levels=20, num_steps=500,
new_level_interval=10000, num_per_step=10000,
thread_steps=1, num_particles=1000, lam=10.0,
beta=100, seed=None, verbose=True, outputfiles_basename=None,
backend='memory')
def __init__(self, likelihood, priors, outdir="outdir", label="label", use_ratio=False, plot=False,
exit_code=77, skip_import_verification=False, temporary_directory=True, **kwargs):
super(DNest4, self).__init__(
likelihood=likelihood,
priors=priors,
outdir=outdir,
label=label,
use_ratio=use_ratio,
plot=plot,
skip_import_verification=skip_import_verification,
exit_code=exit_code,
**kwargs
)
likelihood=likelihood, priors=priors, outdir=outdir, label=label,
use_ratio=use_ratio, plot=plot, skip_import_verification=skip_import_verification,
exit_code=exit_code, **kwargs)
self.num_particles = self.kwargs["num_particles"]
self.max_num_levels = self.kwargs["max_num_levels"]
......@@ -151,6 +119,13 @@ class DNest4(NestedSampler):
self._backend = self.kwargs["backend"]
self.use_temporary_directory = temporary_directory
self.start_time = np.nan
self.sampler = None
self._information = np.nan
self._last_live_sample_info = np.nan
self._outputfiles_basename = None
self._temporary_outputfiles_basename = None
signal.signal(signal.SIGTERM, self.write_current_state_and_exit)
signal.signal(signal.SIGINT, self.write_current_state_and_exit)
signal.signal(signal.SIGALRM, self.write_current_state_and_exit)
......@@ -180,26 +155,19 @@ class DNest4(NestedSampler):
self._highs = np.array(highs)
self._lows = np.array(lows)
self._from_prior = self.get_random_draw_from_prior
self._dnest4_model = _DNest4Model(self.log_likelihood, self._from_prior, self._widths,
self._dnest4_model = _DNest4Model(self.log_likelihood, self.get_random_draw_from_prior, self._widths,
self._centers, self._highs, self._lows)
def _set_backend(self):
import dnest4
if self._backend == 'csv':
# for CSVBackend, which is output data to disk
backend = dnest4.backends.CSVBackend("{}/dnest4{}/".format(self.outdir, self.label), sep=" ")
# change to original
return dnest4.backends.CSVBackend("{}/dnest4{}/".format(self.outdir, self.label), sep=" ")
else:
# for the MemoryBackend, which is output data to memory
backend = dnest4.backends.MemoryBackend()
return backend
return dnest4.backends.MemoryBackend()
def _set_dnest4_kwargs(self):
dnest4_keys = ["num_steps", "new_level_interval", "lam", "beta", "seed"]
self.dnest4_kwargs = {key: self.kwargs[key] for key in dnest4_keys}
return self.dnest4_kwargs
def run_sampler(self):
import dnest4
......@@ -233,17 +201,11 @@ class DNest4(NestedSampler):
if self._backend == 'memory':
self._last_live_sample_info = pd.DataFrame(self.sampler.backend.sample_info[-1])
self.result.log_likelihood_evaluations = self._last_live_sample_info['log_likelihood']
self.result.samples = np.array(self.sampler.backend.posterior_samples)
print("here")
print(self.sampler.backend.posterior_samples)
print(self.result.samples)
else:
sample_info_path = './' + self.kwargs["outputfiles_basename"] + '/sample_info.txt'
sample_info = np.genfromtxt(sample_info_path, comments='#', names=True)
self.result.log_likelihood_evaluations = sample_info['log_likelihood']
self.result.samples = np.array(self.sampler.backend.posterior_samples)
self.result.sampler_output = out
......@@ -262,36 +224,7 @@ class DNest4(NestedSampler):
def _verify_kwargs_against_default_kwargs(self):
self.outputfiles_basename = self.kwargs.pop("outputfiles_basename", None)
# if self.kwargs['backend_callback'] is None:
# self.kwargs['backend_callback'] = self._backend_callback
NestedSampler._verify_kwargs_against_default_kwargs(self)
# def _backend_callback(self, *args, **kwargs):
# if self.use_temporary_directory:
# self._copy_temporary_directory_contents_to_proper_path()
# self._calculate_and_save_sampling_time()
def _setup_run_directory(self):
"""
If using a temporary directory, the output directory is moved to the
temporary directory.
"""
if self.use_temporary_directory:
temporary_outputfiles_basename = tempfile.TemporaryDirectory().name
self.temporary_outputfiles_basename = temporary_outputfiles_basename
if os.path.exists(self.outputfiles_basename):
distutils.dir_util.copy_tree(self.outputfiles_basename, self.temporary_outputfiles_basename)
check_directory_exists_and_if_not_mkdir(temporary_outputfiles_basename)
self.kwargs["outputfiles_basename"] = self.temporary_outputfiles_basename
logger.info("Using temporary file {}".format(temporary_outputfiles_basename))
else:
check_directory_exists_and_if_not_mkdir(self.outputfiles_basename)
self.kwargs["outputfiles_basename"] = self.outpuxtfiles_basename
logger.info("Using output file {}".format(self.outputfiles_basename))
super(DNest4, self)._verify_kwargs_against_default_kwargs()
def _check_and_load_sampling_time_file(self):
self.time_file_path = self.kwargs["outputfiles_basename"] + '/sampling_time.dat'
......@@ -355,7 +288,7 @@ class DNest4(NestedSampler):
self._calculate_and_save_sampling_time()
if self.use_temporary_directory:
self._move_temporary_directory_to_proper_path()
os._exit(self.exit_code)
sys.exit(self.exit_code)
def _move_temporary_directory_to_proper_path(self):
"""
......
import importlib
import os
import tempfile
import shutil
import distutils.dir_util
import signal
import time
import datetime
import sys
import numpy as np
......@@ -175,7 +175,7 @@ class Pymultinest(NestedSampler):
self._calculate_and_save_sampling_time()
if self.use_temporary_directory:
self._move_temporary_directory_to_proper_path()
os._exit(self.exit_code)
sys.exit(self.exit_code)
def _copy_temporary_directory_contents_to_proper_path(self):
"""
......@@ -239,26 +239,6 @@ class Pymultinest(NestedSampler):
self.result.sampling_time = datetime.timedelta(seconds=self.total_sampling_time)
return self.result
def _setup_run_directory(self):
"""
If using a temporary directory, the output directory is moved to the
temporary directory.
"""
if self.use_temporary_directory:
temporary_outputfiles_basename = tempfile.TemporaryDirectory().name
self.temporary_outputfiles_basename = temporary_outputfiles_basename
if os.path.exists(self.outputfiles_basename):
distutils.dir_util.copy_tree(self.outputfiles_basename, self.temporary_outputfiles_basename)
check_directory_exists_and_if_not_mkdir(temporary_outputfiles_basename)
self.kwargs["outputfiles_basename"] = self.temporary_outputfiles_basename
logger.info("Using temporary file {}".format(temporary_outputfiles_basename))
else:
check_directory_exists_and_if_not_mkdir(self.outputfiles_basename)
self.kwargs["outputfiles_basename"] = self.outputfiles_basename
logger.info("Using output file {}".format(self.outputfiles_basename))
def _check_and_load_sampling_time_file(self):
self.time_file_path = self.kwargs["outputfiles_basename"] + '/sampling_time.dat'
if os.path.exists(self.time_file_path):
......
......@@ -6,7 +6,6 @@ import inspect
import os
import shutil
import signal
import tempfile
import time
import numpy as np
......@@ -287,6 +286,7 @@ class Ultranest(NestedSampler):
stepsampler = self.kwargs.pop("step_sampler", None)
self._setup_run_directory()
self.kwargs["log_dir"] = self.kwargs.pop("outputfiles_basename")
self._check_and_load_sampling_time_file()
# use reactive nested sampler when no live points are given
......@@ -326,30 +326,6 @@ class Ultranest(NestedSampler):
return self.result
def _setup_run_directory(self):
"""
If using a temporary directory, the output directory is moved to the
temporary directory and symlinked back.
"""
if self.use_temporary_directory:
temporary_outputfiles_basename = tempfile.TemporaryDirectory().name
self.temporary_outputfiles_basename = temporary_outputfiles_basename
if os.path.exists(self.outputfiles_basename):
distutils.dir_util.copy_tree(
self.outputfiles_basename, self.temporary_outputfiles_basename
)
check_directory_exists_and_if_not_mkdir(temporary_outputfiles_basename)
self.kwargs["log_dir"] = self.temporary_outputfiles_basename
logger.info(
"Using temporary file {}".format(temporary_outputfiles_basename)
)
else:
check_directory_exists_and_if_not_mkdir(self.outputfiles_basename)
self.kwargs["log_dir"] = self.outputfiles_basename
logger.info("Using output file {}".format(self.outputfiles_basename))
def _clean_up_run_directory(self):
if self.use_temporary_directory:
self._move_temporary_directory_to_proper_path()
......
import unittest
from mock import MagicMock
import bilby
class TestDnest4(unittest.TestCase):
def setUp(self):
self.likelihood = MagicMock()
self.priors = bilby.core.prior.PriorDict(
dict(a=bilby.core.prior.Uniform(0, 1), b=bilby.core.prior.Uniform(0, 1))
)
self.sampler = bilby.core.sampler.DNest4(
self.likelihood,
self.priors,
outdir="outdir",
label="label",
use_ratio=False,
plot=False,
skip_import_verification=True,
)
def tearDown(self):
del self.likelihood
del self.priors
del self.sampler
def test_default_kwargs(self):
expected = dict(
max_num_levels=20, num_steps=500,
new_level_interval=10000, num_per_step=10000,
thread_steps=1, num_particles=1000, lam=10.0,
beta=100, seed=None, verbose=True, backend='memory'
)
for key in self.sampler.kwargs.keys():
print(
"key={}, expected={}, actual={}".format(
key, expected[key], self.sampler.kwargs[key]
)
)
self.assertDictEqual(expected, self.sampler.kwargs)
def test_translate_kwargs(self):
expected = dict(
max_num_levels=20, num_steps=500,
new_level_interval=10000, num_per_step=10000,
thread_steps=1, num_particles=1000, lam=10.0,
beta=100, seed=None, verbose=True, backend='memory'
)
for equiv in bilby.core.sampler.base_sampler.NestedSampler.npoints_equiv_kwargs:
new_kwargs = self.sampler.kwargs.copy()
del new_kwargs["num_particles"]
new_kwargs[equiv] = 1000
self.sampler.kwargs = new_kwargs
self.assertDictEqual(expected, self.sampler.kwargs)
if __name__ == "__main__":
unittest.main()
......@@ -40,6 +40,15 @@ class TestRunningSamplers(unittest.TestCase):
resume=False,
)
def test_run_dnest4(self):
_ = bilby.run_sampler(
likelihood=self.likelihood,
priors=self.priors,
sampler="dnest4",
nlive=100,
save=False,
)
def test_run_dynesty(self):
_ = bilby.run_sampler(
likelihood=self.likelihood,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment