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

Merge branch 'add_prior_tests' into 'master'

Add prior tests

See merge request Monash/tupak!196
parents b0382bfd 368b3a20
No related branches found
No related tags found
No related merge requests found
......@@ -19,6 +19,7 @@ Changes currently on master, but not under a tag.
- Adds plotting of the prior on 1D marginal distributions of corner plots
- Adds a method to plot time-domain GW data
- Hyperparameter estimation now enables the user to provide the single event evidences
- Prior and child classes now implement the \_\_eq\_\_ magic method for comparisons
### Changes
- Fix construct_cbc_derived_parameters
......@@ -27,6 +28,8 @@ Changes currently on master, but not under a tag.
- PowerSpectralDensity structure modified
- Fixed bug in get_open_data
- .prior files are no longer created. The prior is stored in the result object.
- Changed the way repr works for priors. The repr can now be used to
re-instantiate the Prior in most cases
- Users can now choose to overwrite existing result files, rather than creating
a .old file.
......
......@@ -12,11 +12,9 @@ class TestBBHPriorSet(unittest.TestCase):
self.base_directory =\
'/'.join(os.path.dirname(
os.path.abspath(sys.argv[0])).split('/')[:-1])
self.filename =\
self.base_directory + '/tupak/gw/prior_files/GW150914.prior'
self.filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'prior_files/binary_black_holes.prior')
self.default_prior = tupak.gw.prior.BBHPriorSet(
filename=self.base_directory\
+ '/tupak/gw/prior_files/binary_black_holes.prior')
filename=self.filename)
def tearDown(self):
del self.prior_dict
......
mass_1 = Uniform(name='mass_1', minimum=20, maximum=100)
mass_2 = Uniform(name='mass_2', minimum=20, maximum=100)
chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100)
total_mass = Uniform(name='total_mass', minimum=10, maximum=200)
mass_ratio = Uniform(name='mass_ratio', minimum=0.125, maximum=1)
symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=8 / 81, maximum=0.25)
# These are the default priors we use for BBH systems.
# Note that you may wish to use more specific mass and distance parameters.
# These commands are all known to tupak.gw.prior.
# Lines beginning "#" are ignored.
mass_1 = Uniform(name='mass_1', minimum=5, maximum=100)
mass_2 = Uniform(name='mass_2', minimum=5, maximum=100)
# chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100)
# total_mass = Uniform(name='total_mass', minimum=10, maximum=200)
# mass_ratio = Uniform(name='mass_ratio', minimum=0.125, maximum=1)
# symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=8 / 81, maximum=0.25)
a_1 = Uniform(name='a_1', minimum=0, maximum=0.8)
a_2 = Uniform(name='a_2', minimum=0, maximum=0.8)
tilt_1 = Sine(name='tilt_1')
tilt_2 = Sine(name='tilt_2')
cos_tilt_1 = Uniform(name='cos_tilt_1', minimum=-1, maximum=1)
cos_tilt_2 = Uniform(name='cos_tilt_2', minimum=-1, maximum=1)
# cos_tilt_1 = Uniform(name='cos_tilt_1', minimum=-1, maximum=1)
# cos_tilt_2 = Uniform(name='cos_tilt_2', minimum=-1, maximum=1)
phi_12 = Uniform(name='phi_12', minimum=0, maximum=2 * np.pi)
phi_jl = Uniform(name='phi_jl', minimum=0, maximum=2 * np.pi)
luminosity_distance = UniformComovingVolume(name='luminosity_distance', minimum=1e2, maximum=5e3)
luminosity_distance = tupak.gw.prior.UniformComovingVolume(name='luminosity_distance', minimum=1e2, maximum=5e3)
dec = Cosine(name='dec')
ra = Uniform(name='ra', minimum=0, maximum=2 * np.pi)
iota = Sine(name='iota')
cos_iota = Uniform(name='cos_iota', minimum=-1, maximum=1)
psi = Uniform(name='psi', minimum=0, maximum=2 * np.pi)
# cos_iota = Uniform(name='cos_iota', minimum=-1, maximum=1)
psi = Uniform(name='psi', minimum=0, maximum=np.pi)
phase = Uniform(name='phase', minimum=0, maximum=2 * np.pi)
......@@ -4,6 +4,8 @@ import unittest
from mock import Mock
import numpy as np
import os
import shutil
from collections import OrderedDict
class TestPriorInstantiationWithoutOptionalPriors(unittest.TestCase):
......@@ -38,6 +40,27 @@ class TestPriorInstantiationWithoutOptionalPriors(unittest.TestCase):
expected_string = "Prior(name='test_name', latex_label='test_label', unit=None, minimum=0, maximum=1)"
self.assertEqual(expected_string, self.prior.__repr__())
def test_base_prob(self):
self.assertTrue(np.isnan(self.prior.prob(5)))
def test_base_ln_prob(self):
self.prior.prob = lambda val: val
self.assertEqual(np.log(5), self.prior.ln_prob(5))
def test_is_in_prior(self):
self.prior.minimum = 0
self.prior.maximum = 1
val_below = self.prior.minimum - 0.1
val_at_minimum = self.prior.minimum
val_in_prior = (self.prior.minimum + self.prior.maximum)/2.
val_at_maximum = self.prior.maximum
val_above = self.prior.maximum + 0.1
self.assertTrue(self.prior.is_in_prior_range(val_at_minimum))
self.assertTrue(self.prior.is_in_prior_range(val_at_maximum))
self.assertTrue(self.prior.is_in_prior_range(val_in_prior))
self.assertFalse(self.prior.is_in_prior_range(val_below))
self.assertFalse(self.prior.is_in_prior_range(val_above))
class TestPriorName(unittest.TestCase):
......@@ -113,7 +136,8 @@ class TestPriorClasses(unittest.TestCase):
tupak.gw.prior.UniformComovingVolume(name='test', minimum=2e2, maximum=5e3),
tupak.core.prior.Sine(name='test', unit='unit'),
tupak.core.prior.Cosine(name='test', unit='unit'),
tupak.core.prior.Interped(name='test', unit='unit', xx=np.linspace(0, 10, 1000), yy=np.linspace(0, 10, 1000) ** 4,
tupak.core.prior.Interped(name='test', unit='unit', xx=np.linspace(0, 10, 1000),
yy=np.linspace(0, 10, 1000) ** 4,
minimum=3, maximum=5),
tupak.core.prior.TruncatedGaussian(name='test', unit='unit', mu=1, sigma=0.4, minimum=-1, maximum=1),
tupak.core.prior.TruncatedNormal(name='test', unit='unit', mu=1, sigma=0.4, minimum=-1, maximum=1),
......@@ -169,9 +193,6 @@ class TestPriorClasses(unittest.TestCase):
def test_probability_above_domain(self):
"""Test that the prior probability is non-negative in domain of validity and zero outside."""
for prior in self.priors:
# skip delta function prior in this case
if isinstance(prior, tupak.core.prior.DeltaFunction):
continue
if prior.maximum != np.inf:
outside_domain = np.linspace(prior.maximum + 1, prior.maximum + 1e4, 1000)
self.assertTrue(all(prior.prob(outside_domain) == 0))
......@@ -179,9 +200,6 @@ class TestPriorClasses(unittest.TestCase):
def test_probability_below_domain(self):
"""Test that the prior probability is non-negative in domain of validity and zero outside."""
for prior in self.priors:
# skip delta function prior in this case
if isinstance(prior, tupak.core.prior.DeltaFunction):
continue
if prior.minimum != -np.inf:
outside_domain = np.linspace(prior.minimum - 1e4, prior.minimum - 1, 1000)
self.assertTrue(all(prior.prob(outside_domain) == 0))
......@@ -189,9 +207,6 @@ class TestPriorClasses(unittest.TestCase):
def test_probability_in_domain(self):
"""Test that the prior probability is non-negative in domain of validity and zero outside."""
for prior in self.priors:
# skip delta function prior in this case
if isinstance(prior, tupak.core.prior.DeltaFunction):
continue
if prior.minimum == -np.inf:
prior.minimum = -1e5
if prior.maximum == np.inf:
......@@ -242,6 +257,201 @@ class TestPriorClasses(unittest.TestCase):
else:
self.assertEqual('unit', prior.unit)
def test_eq_different_classes(self):
for i in range(len(self.priors)):
for j in range(len(self.priors)):
if i == j:
self.assertEqual(self.priors[i], self.priors[j])
else:
self.assertNotEqual(self.priors[i], self.priors[j])
def test_eq_other_condition(self):
prior_1 = tupak.core.prior.PowerLaw(name='test', unit='unit', alpha=0, minimum=0, maximum=1)
prior_2 = tupak.core.prior.PowerLaw(name='test', unit='unit', alpha=0, minimum=0, maximum=1.5)
self.assertNotEqual(prior_1, prior_2)
def test_eq_different_keys(self):
prior_1 = tupak.core.prior.PowerLaw(name='test', unit='unit', alpha=0, minimum=0, maximum=1)
prior_2 = tupak.core.prior.PowerLaw(name='test', unit='unit', alpha=0, minimum=0, maximum=1)
prior_2.other_key = 5
self.assertNotEqual(prior_1, prior_2)
def test_np_array_eq(self):
prior_1 = tupak.core.prior.PowerLaw(name='test', unit='unit', alpha=0, minimum=0, maximum=1)
prior_2 = tupak.core.prior.PowerLaw(name='test', unit='unit', alpha=0, minimum=0, maximum=1)
prior_1.array_attribute = np.array([1, 2, 3])
prior_2.array_attribute = np.array([2, 2, 3])
self.assertNotEqual(prior_1, prior_2)
def test_repr(self):
for prior in self.priors:
if isinstance(prior, tupak.core.prior.Interped):
continue # we cannot test this because of the numpy arrays
elif isinstance(prior, tupak.gw.prior.UniformComovingVolume):
repr_prior_string = 'tupak.gw.prior.' + repr(prior)
else:
repr_prior_string = 'tupak.core.prior.' + repr(prior)
repr_prior = eval(repr_prior_string)
self.assertEqual(prior, repr_prior)
class TestPriorSet(unittest.TestCase):
def setUp(self):
self.first_prior = tupak.core.prior.Uniform(name='a', minimum=0, maximum=1, unit='kg')
self.second_prior = tupak.core.prior.PowerLaw(name='b', alpha=3, minimum=1, maximum=2, unit='m/s')
self.third_prior = tupak.core.prior.DeltaFunction(name='c', peak=42, unit='m')
self.prior_dict = dict(mass=self.first_prior,
speed=self.second_prior,
length=self.third_prior)
self.prior_set_from_dict = tupak.core.prior.PriorSet(dictionary=self.prior_dict)
self.default_prior_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'prior_files/binary_black_holes.prior')
self.prior_set_from_file = tupak.core.prior.PriorSet(filename=self.default_prior_file)
def tearDown(self):
del self.first_prior
del self.second_prior
del self.third_prior
del self.prior_dict
del self.prior_set_from_dict
del self.default_prior_file
del self.prior_set_from_file
def test_prior_set_is_ordered_dict(self):
self.assertIsInstance(self.prior_set_from_dict, OrderedDict)
def test_prior_set_has_correct_length(self):
self.assertEqual(3, len(self.prior_set_from_dict))
def test_prior_set_has_expected_priors(self):
self.assertDictEqual(self.prior_dict, dict(self.prior_set_from_dict))
# Removed for now as it does not create the outdir in the Gitlab CI
# def test_write_to_file(self):
# outdir = 'prior_set_test_outdir'
# label = 'test_label'
# label_dot_prior = label + '.prior'
# current_dir_path = os.path.dirname(os.path.realpath(__file__))
# outdir_path = os.path.join(current_dir_path, outdir)
# outfile_path = os.path.join(outdir_path, label_dot_prior)
# self.prior_set_from_dict.write_to_file(outdir=outdir, label=label)
# self.assertTrue(os.path.isdir(outdir_path))
# self.assertTrue(os.listdir(outdir_path)[0] == label_dot_prior)
# with open(outfile_path, 'r') as f:
# expected_outfile = [
# 'speed = PowerLaw(alpha=3, minimum=1, maximum=2, name=\'b\', latex_label=\'b\', unit=\'m/s\')\n',
# 'mass = Uniform(minimum=0, maximum=1, name=\'a\', latex_label=\'a\', unit=\'kg\')\n',
# 'length = DeltaFunction(peak=42, name=\'c\', latex_label=\'c\', unit=\'m\')\n']
# self.assertListEqual(sorted(expected_outfile), sorted(f.readlines()))
# shutil.rmtree(outdir_path)
def test_read_from_file(self):
expected = dict(mass_1=tupak.core.prior.Uniform(name='mass_1', minimum=5, maximum=100),
mass_2=tupak.core.prior.Uniform(name='mass_2', minimum=5, maximum=100),
a_1=tupak.core.prior.Uniform(name='a_1', minimum=0, maximum=0.8),
a_2=tupak.core.prior.Uniform(name='a_2', minimum=0, maximum=0.8),
tilt_1=tupak.core.prior.Sine(name='tilt_1'),
tilt_2=tupak.core.prior.Sine(name='tilt_2'),
phi_12=tupak.core.prior.Uniform(name='phi_12', minimum=0, maximum=2 * np.pi),
phi_jl=tupak.core.prior.Uniform(name='phi_jl', minimum=0, maximum=2 * np.pi),
luminosity_distance=tupak.gw.prior.UniformComovingVolume(name='luminosity_distance',
minimum=1e2, maximum=5e3),
dec=tupak.core.prior.Cosine(name='dec'),
ra=tupak.core.prior.Uniform(name='ra', minimum=0, maximum=2 * np.pi),
iota=tupak.core.prior.Sine(name='iota'),
psi=tupak.core.prior.Uniform(name='psi', minimum=0, maximum=np.pi),
phase=tupak.core.prior.Uniform(name='phase', minimum=0, maximum=2 * np.pi)
)
self.assertDictEqual(expected, self.prior_set_from_file)
def test_convert_floats_to_delta_functions(self):
self.prior_set_from_dict['d'] = 5
self.prior_set_from_dict['e'] = 7.3
self.prior_set_from_dict['f'] = 'unconvertable'
self.prior_set_from_dict.convert_floats_to_delta_functions()
expected = dict(mass=tupak.core.prior.Uniform(name='a', minimum=0, maximum=1, unit='kg'),
speed=tupak.core.prior.PowerLaw(name='b', alpha=3, minimum=1, maximum=2, unit='m/s'),
length=tupak.core.prior.DeltaFunction(name='c', peak=42, unit='m'),
d=tupak.core.prior.DeltaFunction(peak=5),
e=tupak.core.prior.DeltaFunction(peak=7.3),
f='unconvertable')
self.assertDictEqual(expected, self.prior_set_from_dict)
def test_prior_set_from_dict_but_using_a_string(self):
prior_set = tupak.core.prior.PriorSet(dictionary=self.default_prior_file)
expected = dict(mass_1=tupak.core.prior.Uniform(name='mass_1', minimum=5, maximum=100),
mass_2=tupak.core.prior.Uniform(name='mass_2', minimum=5, maximum=100),
a_1=tupak.core.prior.Uniform(name='a_1', minimum=0, maximum=0.8),
a_2=tupak.core.prior.Uniform(name='a_2', minimum=0, maximum=0.8),
tilt_1=tupak.core.prior.Sine(name='tilt_1'),
tilt_2=tupak.core.prior.Sine(name='tilt_2'),
phi_12=tupak.core.prior.Uniform(name='phi_12', minimum=0, maximum=2 * np.pi),
phi_jl=tupak.core.prior.Uniform(name='phi_jl', minimum=0, maximum=2 * np.pi),
luminosity_distance=tupak.gw.prior.UniformComovingVolume(name='luminosity_distance',
minimum=1e2, maximum=5e3),
dec=tupak.core.prior.Cosine(name='dec'),
ra=tupak.core.prior.Uniform(name='ra', minimum=0, maximum=2 * np.pi),
iota=tupak.core.prior.Sine(name='iota'),
psi=tupak.core.prior.Uniform(name='psi', minimum=0, maximum=np.pi),
phase=tupak.core.prior.Uniform(name='phase', minimum=0, maximum=2 * np.pi)
)
self.assertDictEqual(expected, prior_set)
def test_dict_argument_is_not_string_or_dict(self):
with self.assertRaises(ValueError):
tupak.core.prior.PriorSet(dictionary=list())
def test_sample_subset_correct_size(self):
size = 7
samples = self.prior_set_from_dict.sample_subset(keys=self.prior_set_from_dict.keys(), size=size)
self.assertEqual(len(self.prior_set_from_dict), len(samples))
for key in samples:
self.assertEqual(size, len(samples[key]))
def test_sample_subset_correct_size_when_non_priors_in_dict(self):
self.prior_set_from_dict['asdf'] = 'not_a_prior'
samples = self.prior_set_from_dict.sample_subset(keys=self.prior_set_from_dict.keys())
self.assertEqual(len(self.prior_set_from_dict) - 1, len(samples))
def test_sample_subset_with_actual_subset(self):
size = 3
samples = self.prior_set_from_dict.sample_subset(keys=['length'], size=size)
expected = dict(length=np.array([42., 42., 42.]))
self.assertTrue(np.array_equal(expected['length'], samples['length']))
def test_sample(self):
size = 7
np.random.seed(42)
samples1 = self.prior_set_from_dict.sample_subset(keys=self.prior_set_from_dict.keys(), size=size)
np.random.seed(42)
samples2 = self.prior_set_from_dict.sample(size=size)
self.assertEqual(samples1.keys(), samples2.keys())
for key in samples1:
self.assertTrue(np.array_equal(samples1[key], samples2[key]))
def test_prob(self):
samples = self.prior_set_from_dict.sample_subset(keys=['mass', 'speed'])
expected = self.first_prior.prob(samples['mass']) * self.second_prior.prob(samples['speed'])
self.assertEqual(expected, self.prior_set_from_dict.prob(samples))
def test_ln_prob(self):
samples = self.prior_set_from_dict.sample_subset(keys=['mass', 'speed'])
expected = self.first_prior.ln_prob(samples['mass']) + self.second_prior.ln_prob(samples['speed'])
self.assertEqual(expected, self.prior_set_from_dict.ln_prob(samples))
def test_rescale(self):
theta = [0.5, 0.5, 0.5]
expected = [self.first_prior.rescale(0.5),
self.second_prior.rescale(0.5),
self.third_prior.rescale(0.5)]
self.assertListEqual(sorted(expected), sorted(self.prior_set_from_dict.rescale(
keys=self.prior_set_from_dict.keys(), theta=theta)))
def test_redundancy(self):
for key in self.prior_set_from_dict.keys():
self.assertFalse(self.prior_set_from_dict.test_redundancy(key=key))
class TestFillPrior(unittest.TestCase):
......@@ -250,9 +460,9 @@ class TestFillPrior(unittest.TestCase):
self.likelihood.parameters = dict(a=0, b=0, c=0, d=0, asdf=0, ra=1)
self.likelihood.non_standard_sampling_parameter_keys = dict(t=8)
self.priors = dict(a=1, b=1.1, c='string', d=tupak.core.prior.Uniform(0, 1))
self.priors = tupak.core.prior.PriorSet(self.priors)
self.default_prior_file = os.path.join('/'.join(os.path.dirname(__file__).split('/')[:-1]), 'tupak', 'gw',
'prior_files', 'binary_black_holes.prior')
self.priors = tupak.core.prior.PriorSet(dictionary=self.priors)
self.default_prior_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'prior_files/binary_black_holes.prior')
self.priors.fill_priors(self.likelihood, self.default_prior_file)
def tearDown(self):
......@@ -282,5 +492,22 @@ class TestFillPrior(unittest.TestCase):
self.assertIsInstance(self.priors['ra'], tupak.core.prior.Uniform)
class TestCreateDefaultPrior(unittest.TestCase):
def test_none_behaviour(self):
self.assertIsNone(tupak.core.prior.create_default_prior(name='name', default_priors_file=None))
def test_bbh_params(self):
prior_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'prior_files/binary_black_holes.prior')
prior_set = tupak.core.prior.PriorSet(filename=prior_file)
for prior in prior_set:
self.assertEqual(prior_set[prior], tupak.core.prior.create_default_prior(name=prior,
default_priors_file=prior_file))
def test_unknown_prior(self):
prior_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'prior_files/binary_black_holes.prior')
self.assertIsNone(tupak.core.prior.create_default_prior(name='name', default_priors_file=prior_file))
if __name__ == '__main__':
unittest.main()
File moved
......@@ -12,6 +12,7 @@ from future.utils import iteritems
from tupak.core.utils import logger
from tupak.core import utils
import tupak # noqa
import inspect
class PriorSet(OrderedDict):
......@@ -277,7 +278,6 @@ def create_default_prior(name, default_priors_file=None):
class Prior(object):
_default_latex_labels = dict()
def __init__(self, name=None, latex_label=None, unit=None, minimum=-np.inf,
......@@ -313,6 +313,20 @@ class Prior(object):
"""
return self.sample()
def __eq__(self, other):
if self.__class__ != other.__class__:
return False
if sorted(self.__dict__.keys()) != sorted(other.__dict__.keys()):
return False
for key in self.__dict__:
if type(self.__dict__[key]) is np.ndarray:
if not np.array_equal(self.__dict__[key], other.__dict__[key]):
return False
else:
if not self.__dict__[key] == other.__dict__[key]:
return False
return True
def sample(self, size=None):
"""Draw a sample from the prior
......@@ -374,6 +388,20 @@ class Prior(object):
"""
return np.log(self.prob(val))
def is_in_prior_range(self, val):
"""Returns True if val is in the prior boundaries, zero otherwise
Parameters
----------
val: float
Returns
-------
np.nan
"""
return (val >= self.minimum) & (val <= self.maximum)
@staticmethod
def test_valid_for_rescaling(val):
"""Test if 0 < val < 1
......@@ -394,38 +422,23 @@ class Prior(object):
def __repr__(self):
"""Overrides the special method __repr__.
Should return a representation of this instance that resembles how it is instantiated
Returns a representation of this instance that resembles how it is instantiated.
Works correctly for all child classes
Returns
-------
str: A string representation of this instance
"""
return self._subclass_repr_helper()
def _subclass_repr_helper(self, subclass_args=iter([])):
"""Helps out subclass _repr__ methods by creating a common template
Parameters
----------
subclass_args: list, optional
List of attributes in the subclass instance
Returns
-------
str: A string representation for this subclass instance.
"""
subclass_args = inspect.getargspec(self.__init__).args
subclass_args.pop(0)
prior_name = self.__class__.__name__
args = ['name', 'latex_label', 'unit', 'minimum', 'maximum']
args.extend(subclass_args)
property_names = [p for p in dir(self.__class__) if isinstance(getattr(self.__class__, p), property)]
dict_with_properties = self.__dict__.copy()
for key in property_names:
dict_with_properties[key] = getattr(self, key)
args = ', '.join(['{}={}'.format(key, repr(dict_with_properties[key])) for key in args])
args = ', '.join(['{}={}'.format(key, repr(dict_with_properties[key])) for key in subclass_args])
return "{}({})".format(prior_name, args)
@property
......@@ -550,14 +563,8 @@ class DeltaFunction(Prior):
float: np.inf if val = peak, 0 otherwise
"""
if self.peak == val:
return np.inf
else:
return 0
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['peak'])
at_peak = (val == self.peak)
return np.nan_to_num(np.multiply(at_peak, np.inf))
class PowerLaw(Prior):
......@@ -618,13 +625,12 @@ class PowerLaw(Prior):
-------
float: Prior probability of val
"""
in_prior = (val >= self.minimum) & (val <= self.maximum)
if self.alpha == -1:
return np.nan_to_num(1 / val / np.log(self.maximum / self.minimum)) * in_prior
return np.nan_to_num(1 / val / np.log(self.maximum / self.minimum)) * self.is_in_prior_range(val)
else:
return np.nan_to_num(val ** self.alpha * (1 + self.alpha) /
(self.maximum ** (1 + self.alpha) -
self.minimum ** (1 + self.alpha))) * in_prior
self.minimum ** (1 + self.alpha))) * self.is_in_prior_range(val)
def ln_prob(self, val):
"""Return the logarithmic prior probability of val
......@@ -638,19 +644,13 @@ class PowerLaw(Prior):
float:
"""
in_prior = (val >= self.minimum) & (val <= self.maximum)
if self.alpha == -1:
normalising = 1. / np.log(self.maximum / self.minimum)
else:
normalising = (1 + self.alpha) / (self.maximum ** (1 + self.alpha) -
self.minimum ** (1 + self.alpha))
return (self.alpha * np.log(val) + np.log(normalising)) + np.log(1. * in_prior)
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['alpha'])
return (self.alpha * np.log(val) + np.log(normalising)) + np.log(1. * self.is_in_prior_range(val))
class Uniform(Prior):
......@@ -732,10 +732,6 @@ class LogUniform(PowerLaw):
if self.minimum <= 0:
logger.warning('You specified a uniform-in-log prior with minimum={}'.format(self.minimum))
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self)
class Cosine(Prior):
......@@ -779,8 +775,7 @@ class Cosine(Prior):
-------
float: Prior probability of val
"""
in_prior = (val >= self.minimum) & (val <= self.maximum)
return np.cos(val) / 2 * in_prior
return np.cos(val) / 2 * self.is_in_prior_range(val)
class Sine(Prior):
......@@ -825,11 +820,11 @@ class Sine(Prior):
-------
float: Prior probability of val
"""
in_prior = (val >= self.minimum) & (val <= self.maximum)
return np.sin(val) / 2 * in_prior
return np.sin(val) / 2 * self.is_in_prior_range(val)
class Gaussian(Prior):
def __init__(self, mu, sigma, name=None, latex_label=None, unit=None):
"""Gaussian prior with mean mu and width sigma
......@@ -875,10 +870,6 @@ class Gaussian(Prior):
def ln_prob(self, val):
return -0.5 * ((self.mu - val) ** 2 / self.sigma ** 2 + np.log(2 * np.pi * self.sigma ** 2))
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['mu', 'sigma'])
class Normal(Gaussian):
......@@ -964,13 +955,8 @@ class TruncatedGaussian(Prior):
-------
float: Prior probability of val
"""
in_prior = (val >= self.minimum) & (val <= self.maximum)
return np.exp(-(self.mu - val) ** 2 / (2 * self.sigma ** 2)) / (
2 * np.pi) ** 0.5 / self.sigma / self.normalisation * in_prior
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['mu', 'sigma'])
2 * np.pi) ** 0.5 / self.sigma / self.normalisation * self.is_in_prior_range(val)
class TruncatedNormal(TruncatedGaussian):
......@@ -1020,10 +1006,6 @@ class HalfGaussian(TruncatedGaussian):
name=name, latex_label=latex_label,
unit=unit)
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['sigma'])
class HalfNormal(HalfGaussian):
def __init__(self, sigma, name=None, latex_label=None, unit=None):
......@@ -1100,10 +1082,6 @@ class LogNormal(Prior):
def ln_prob(self, val):
return scipy.stats.lognorm.logpdf(val, self.sigma, scale=np.exp(self.mu))
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['mu', 'sigma'])
class LogGaussian(LogNormal):
def __init__(self, mu, sigma, name=None, latex_label=None, unit=None):
......@@ -1175,10 +1153,6 @@ class Exponential(Prior):
def ln_prob(self, val):
return scipy.stats.expon.logpdf(val, scale=self.mu)
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['mu'])
class StudentT(Prior):
def __init__(self, df, mu=0., scale=1., name=None, latex_label=None,
......@@ -1239,10 +1213,6 @@ class StudentT(Prior):
def ln_prob(self, val):
return scipy.stats.t.logpdf(val, self.df, loc=self.mu, scale=self.scale)
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['df', 'mu', 'scale'])
class Beta(Prior):
def __init__(self, alpha, beta, name=None, latex_label=None, unit=None):
......@@ -1320,10 +1290,6 @@ class Beta(Prior):
else:
return -np.inf
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['alpha', 'beta'])
class Logistic(Prior):
def __init__(self, mu, scale, name=None, latex_label=None, unit=None):
......@@ -1379,10 +1345,6 @@ class Logistic(Prior):
def ln_prob(self, val):
return scipy.stats.logistic.logpdf(val, loc=self.mu, scale=self.scale)
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['mu', 'scale'])
class Cauchy(Prior):
def __init__(self, alpha, beta, name=None, latex_label=None, unit=None):
......@@ -1438,10 +1400,6 @@ class Cauchy(Prior):
def ln_prob(self, val):
return scipy.stats.cauchy.logpdf(val, loc=self.alpha, scale=self.beta)
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['alpha', 'beta'])
class Lorentzian(Cauchy):
def __init__(self, alpha, beta, name=None, latex_label=None, unit=None):
......@@ -1522,10 +1480,6 @@ class Gamma(Prior):
def ln_prob(self, val):
return scipy.stats.gamma.logpdf(val, self.k, loc=0., scale=self.theta)
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['k', 'theta'])
class ChiSquared(Gamma):
def __init__(self, nu, name=None, latex_label=None, unit=None):
......@@ -1551,6 +1505,14 @@ class ChiSquared(Gamma):
Gamma.__init__(self, name=name, k=nu / 2., theta=2.,
latex_label=latex_label, unit=unit)
@property
def nu(self):
return int(self.k * 2)
@nu.setter
def nu(self, nu):
self.k = nu / 2.
class Interped(Prior):
......@@ -1595,6 +1557,13 @@ class Interped(Prior):
maximum=np.nanmin(np.array((max(xx), maximum))))
self.__initialize_attributes()
def __eq__(self, other):
if self.__class__ != other.__class__:
return False
if np.array_equal(self.xx, other.xx) and np.array_equal(self.yy, other.yy):
return True
return False
def prob(self, val):
"""Return the prior probability of val.
......@@ -1620,10 +1589,6 @@ class Interped(Prior):
rescaled = float(rescaled)
return rescaled
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['xx', 'yy'])
@property
def minimum(self):
"""Return minimum of the prior distribution.
......@@ -1716,7 +1681,3 @@ class FromFile(Interped):
logger.warning("Can't load {}.".format(self.id))
logger.warning("Format should be:")
logger.warning(r"x\tp(x)")
def __repr__(self):
"""Call to helper method in the super class."""
return Prior._subclass_repr_helper(self, subclass_args=['id'])
This diff is collapsed.
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