Commit a407eb3c authored by Gregory Ashton's avatar Gregory Ashton

Merge branch 'improve-prior-reading' into 'master'

Improve prior reading

See merge request lscsoft/bilby!501
parents 4a340c1e 8b4b135e
Pipeline #67231 passed with stages
in 6 minutes and 53 seconds
from __future__ import division
from importlib import import_module
import os
from collections import OrderedDict
from future.utils import iteritems
......@@ -11,9 +12,8 @@ from scipy.integrate import cumtrapz
from scipy.interpolate import interp1d
from scipy.special import erf, erfinv
# Keep import bilby statement, it is necessary for some eval() statements
import bilby # noqa
from .utils import logger, infer_args_from_method, check_directory_exists_and_if_not_mkdir
from .utils import (
logger, infer_args_from_method, check_directory_exists_and_if_not_mkdir)
class PriorDict(OrderedDict):
......@@ -112,15 +112,28 @@ class PriorDict(OrderedDict):
for line in f:
if line[0] in comments:
continue
line.replace(' ', '')
elements = line.split('=')
key = elements[0].replace(' ', '')
val = '='.join(elements[1:])
try:
prior[key] = eval(val)
except TypeError as e:
raise TypeError(
"Unable to parse dictionary file {}, bad line: {} = {}. Error message {}"
.format(filename, key, val, e))
val = '='.join(elements[1:]).strip()
cls = val.split('(')[0]
args = '('.join(val.split('(')[1:])[:-1]
if "." in cls:
module = '.'.join(cls.split('.')[:-1])
cls = cls.split('.')[-1]
else:
module = __name__
cls = getattr(import_module(module), cls)
if key.lower() == "conversion_function":
setattr(self, key, cls)
else:
try:
prior[key] = cls.from_repr(args)
except TypeError as e:
raise TypeError(
"Unable to parse dictionary file {}, bad line: {} "
"= {}. Error message {}".format(
filename, key, val, e))
self.update(prior)
def from_dictionary(self, dictionary):
......@@ -661,6 +674,68 @@ class Prior(object):
label = self.name
return label
@classmethod
def from_repr(cls, string):
subclass_args = infer_args_from_method(cls.__init__)
string = string.replace(' ', '')
kwargs = cls._split_repr(string)
for key in kwargs:
val = kwargs[key]
if key not in subclass_args:
raise AttributeError('Unknown argument {} for class {}'.format(
key, cls.__name__))
else:
kwargs[key] = cls._parse_argument_string(val)
return cls(**kwargs)
@classmethod
def _split_repr(cls, string):
subclass_args = infer_args_from_method(cls.__init__)
args = string.split(',')
remove = list()
for ii, key in enumerate(args):
if '(' in key:
args[ii] = ','.join([args[ii], args[ii + 1]]).strip()
remove.append(ii + 1)
remove.reverse()
for ii in remove:
del args[ii]
kwargs = dict()
for ii, arg in enumerate(args):
try:
key, val = arg.split('=')
except ValueError:
logger.debug(
'Reading priors with non-keyword arguments is dangerous!')
key = subclass_args[ii]
val = arg
kwargs[key] = val
return kwargs
@classmethod
def _parse_argument_string(cls, val):
if '(' in val:
other_cls = val.split('(')[0]
vals = '('.join(val.split('(')[1:])[:-1]
if "." in other_cls:
module = '.'.join(other_cls.split('.')[:-1])
other_cls = other_cls.split('.')[-1]
else:
module = __name__
other_cls = getattr(import_module(module), other_cls)
val = other_cls.from_repr(vals)
elif "'" in val:
val = val.strip("'")
elif val == 'None':
val = None
else:
try:
val = eval(val, dict(), dict(np=np))
except NameError:
raise TypeError()
return val
class Constraint(Prior):
......
# These are the default priors for analysing GW150914.
mass_1 = Uniform(name='mass_1', minimum=30, maximum=50, unit='$M_{\\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=20, maximum=40, unit='$M_{\\odot}$', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=30, maximum=50, unit='$M_{\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=20, maximum=40, unit='$M_{\odot}$', boundary=None)
mass_ratio = Constraint(name='mass_ratio', minimum=0.125, maximum=1)
a_1 = Uniform(name='a_1', minimum=0, maximum=0.8, boundary='reflective')
a_2 = Uniform(name='a_2', minimum=0, maximum=0.8, boundary='reflective')
......
......@@ -2,11 +2,11 @@
# Note that you may wish to use more specific mass and distance parameters.
# These commands are all known to bilby.gw.prior.
# Lines beginning "#" are ignored.
mass_1 = Uniform(name='mass_1', minimum=5, maximum=100, unit='$M_{\\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=5, maximum=100, unit='$M_{\\odot}$', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=5, maximum=100, unit='$M_{\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=5, maximum=100, unit='$M_{\odot}$', boundary=None)
mass_ratio = Constraint(name='mass_ratio', minimum=0.125, maximum=1)
# chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100, unit='$M_{\\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=10, maximum=200, unit='$M_{\\odot}$', boundary=None)
# chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100, unit='$M_{\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=10, maximum=200, unit='$M_{\odot}$', boundary=None)
# mass_ratio = Uniform(name='mass_ratio', minimum=0.125, maximum=1, boundary=None)
# symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=8 / 81, maximum=0.25, boundary=None)
chi_1 = bilby.gw.prior.AlignedSpin(name='chi_1', a_prior=Uniform(minimum=0, maximum=0.8), boundary='reflective')
......
......@@ -2,11 +2,11 @@
# Note that you may wish to use more specific mass and distance parameters.
# These commands are all known to bilby.gw.prior.
# Lines beginning "#" are ignored.
mass_1 = Uniform(name='mass_1', minimum=5, maximum=100, unit='$M_{\\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=5, maximum=100, unit='$M_{\\odot}$', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=5, maximum=100, unit='$M_{\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=5, maximum=100, unit='$M_{\odot}$', boundary=None)
mass_ratio = Constraint(name='mass_ratio', minimum=0.125, maximum=1)
# chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100, unit='$M_{\\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=10, maximum=200, unit='$M_{\\odot}$', boundary=None)
# chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100, unit='$M_{\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=10, maximum=200, unit='$M_{\odot}$', boundary=None)
# mass_ratio = Uniform(name='mass_ratio', minimum=0.125, maximum=1, boundary=None)
# symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=8 / 81, maximum=0.25, boundary=None)
a_1 = Uniform(name='a_1', minimum=0, maximum=0.8, boundary='reflective')
......
......@@ -2,11 +2,11 @@
# Note that you may wish to use more specific mass and distance parameters.
# These commands are all known to bilby.gw.prior.
# Lines beginning "#" are ignored.
mass_1 = Uniform(name='mass_1', minimum=1, maximum=2, unit='$M_{\\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=1, maximum=2, unit='$M_{\\odot}$', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=1, maximum=2, unit='$M_{\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=1, maximum=2, unit='$M_{\odot}$', boundary=None)
mass_ratio = Constraint(name='mass_ratio', minimum=0.125, maximum=1)
# chirp_mass = Uniform(name='chirp_mass', minimum=0.87, maximum=1.74, unit='$M_{\\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=2, maximum=4, unit='$M_{\\odot}$', boundary=None)
# chirp_mass = Uniform(name='chirp_mass', minimum=0.87, maximum=1.74, unit='$M_{\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=2, maximum=4, unit='$M_{\odot}$', boundary=None)
# mass_ratio = Uniform(name='mass_ratio', minimum=0.5, maximum=1, boundary=None)
# symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=0.22, maximum=0.25, boundary=None)
chi_1 = bilby.gw.prior.AlignedSpin(a_prior=Uniform(0, 0.05), z_prior=Uniform(-1, 1), name='chi_1', latex_label='$\\chi_1$', boundary='reflective')
......
......@@ -2,11 +2,11 @@
# Note that you may wish to use more specific mass and distance parameters.
# These commands are all known to bilby.gw.prior.
# Lines beginning "#" are ignored.
mass_1 = Uniform(name='mass_1', minimum=1, maximum=2, unit='$M_{\\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=1, maximum=2, unit='$M_{\\odot}$', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=1, maximum=2, unit='$M_{\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=1, maximum=2, unit='$M_{\odot}$', boundary=None)
mass_ratio = Constraint(name='mass_ratio', minimum=0.125, maximum=1)
# chirp_mass = Uniform(name='chirp_mass', minimum=0.87, maximum=1.74, unit='$M_{\\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=2, maximum=4, unit='$M_{\\odot}$', boundary=None)
# chirp_mass = Uniform(name='chirp_mass', minimum=0.87, maximum=1.74, unit='$M_{\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=2, maximum=4, unit='$M_{\odot}$', boundary=None)
# mass_ratio = Uniform(name='mass_ratio', minimum=0.5, maximum=1, boundary=None)
# symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=0.22, maximum=0.25, boundary=None)
a_1 = Uniform(name='a_1', minimum=0, maximum=0.05, boundary='reflective')
......
......@@ -36,7 +36,7 @@ class TestBBHPriorDict(unittest.TestCase):
for key in default.keys()])
names = all([self.bbh_prior_dict[key].name == default[key].name
for key in default.keys()])
boundaries = all([self.bbh_prior_dict[key].boundary is default[key].boundary
boundaries = all([self.bbh_prior_dict[key].boundary == default[key].boundary
for key in default.keys()])
self.assertTrue(all([minima, maxima, names, boundaries]))
......
......@@ -2,11 +2,11 @@
# Note that you may wish to use more specific mass and distance parameters.
# These commands are all known to bilby.gw.prior.
# Lines beginning "#" are ignored.
mass_1 = Uniform(name='mass_1', minimum=5, maximum=100, unit='$M_{\\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=5, maximum=100, unit='$M_{\\odot}$', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=5, maximum=100, unit='$M_{\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=5, maximum=100, unit='$M_{\odot}$', boundary=None)
mass_ratio = Constraint(name='mass_ratio', minimum=0.125, maximum=1)
# chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100, unit='$M_{\\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=10, maximum=200, unit='$M_{\\odot}$', boundary=None)
# chirp_mass = Uniform(name='chirp_mass', minimum=25, maximum=100, unit='$M_{\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=10, maximum=200, unit='$M_{\odot}$', boundary=None)
# mass_ratio = Uniform(name='mass_ratio', minimum=0.125, maximum=1, boundary=None)
# symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=8 / 81, maximum=0.25, boundary=None)
a_1 = Uniform(name='a_1', minimum=0, maximum=0.8, boundary='reflective')
......
......@@ -2,11 +2,11 @@
# Note that you may wish to use more specific mass and distance parameters.
# These commands are all known to bilby.gw.prior.
# Lines beginning "#" are ignored.
mass_1 = Uniform(name='mass_1', minimum=1, maximum=2, unit='$M_{\\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=1, maximum=2, unit='$M_{\\odot}$', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=1, maximum=2, unit='$M_{\odot}$', boundary=None)
mass_2 = Uniform(name='mass_2', minimum=1, maximum=2, unit='$M_{\odot}$', boundary=None)
mass_ratio = Constraint(name='mass_ratio', minimum=0.125, maximum=1)
# chirp_mass = Uniform(name='chirp_mass', minimum=0.87, maximum=1.74, unit='$M_{\\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=2, maximum=4, unit='$M_{\\odot}$', boundary=None)
# chirp_mass = Uniform(name='chirp_mass', minimum=0.87, maximum=1.74, unit='$M_{\odot}$', boundary=None)
# total_mass = Uniform(name='total_mass', minimum=2, maximum=4, unit='$M_{\odot}$', boundary=None)
# mass_ratio = Uniform(name='mass_ratio', minimum=0.5, maximum=1, boundary=None)
# symmetric_mass_ratio = Uniform(name='symmetric_mass_ratio', minimum=0.22, maximum=0.25, boundary=None)
chi_1 = bilby.gw.prior.AlignedSpin(a_prior=Uniform(0, 0.05), z_prior=Uniform(-1, 1), name='chi_1', latex_label='$\\chi_1$', boundary='reflective')
......
......@@ -592,7 +592,7 @@ class TestPriorDict(unittest.TestCase):
self.assertTrue(line in expected)
def test_from_dict_with_string(self):
string_prior = "bilby.core.prior.PowerLaw(name='b', alpha=3, minimum=1, maximum=2, unit='m/s', " \
string_prior = "PowerLaw(name='b', alpha=3, minimum=1, maximum=2, unit='m/s', " \
"boundary=None)"
self.priors['speed'] = string_prior
from_dict = bilby.core.prior.PriorDict(dictionary=self.priors)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment