Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • john-veitch/bilby
  • duncanmmacleod/bilby
  • colm.talbot/bilby
  • lscsoft/bilby
  • matthew-pitkin/bilby
  • salvatore-vitale/tupak
  • charlie.hoy/bilby
  • bfarr/bilby
  • virginia.demilio/bilby
  • vivien/bilby
  • eric-howell/bilby
  • sebastian-khan/bilby
  • rhys.green/bilby
  • moritz.huebner/bilby
  • joseph.mills/bilby
  • scott.coughlin/bilby
  • matthew.carney/bilby
  • hyungwon.lee/bilby
  • monica.rizzo/bilby
  • christopher-berry/bilby
  • lindsay.demarchi/bilby
  • kaushik.rao/bilby
  • charles.kimball/bilby
  • andrew.matas/bilby
  • juan.calderonbustillo/bilby
  • patrick-meyers/bilby
  • hannah.middleton/bilby
  • eve.chase/bilby
  • grant.meadors/bilby
  • khun.phukon/bilby
  • sumeet.kulkarni/bilby
  • daniel.reardon/bilby
  • cjhaster/bilby
  • sylvia.biscoveanu/bilby
  • james-clark/bilby
  • meg.millhouse/bilby
  • joshua.willis/bilby
  • nikhil.sarin/bilby
  • paul.easter/bilby
  • youngmin/bilby
  • daniel-williams/bilby
  • shanika.galaudage/bilby
  • bruce.edelman/bilby
  • avi.vajpeyi/bilby
  • isobel.romero-shaw/bilby
  • andrew.kim/bilby
  • dominika.zieba/bilby
  • jonathan.davies/bilby
  • marc.arene/bilby
  • srishti.tiwari/bilby-tidal-heating-eccentric
  • aditya.vijaykumar/bilby
  • michael.williams/bilby
  • cecilio.garcia-quiros/bilby
  • rory-smith/bilby
  • maite.mateu-lucena/bilby
  • wushichao/bilby
  • kaylee.desoto/bilby
  • brandon.piotrzkowski/bilby
  • rossella.gamba/bilby
  • hunter.gabbard/bilby
  • deep.chatterjee/bilby
  • tathagata.ghosh/bilby
  • arunava.mukherjee/bilby
  • philip.relton/bilby
  • reed.essick/bilby
  • pawan.gupta/bilby
  • francisco.hernandez/bilby
  • rhiannon.udall/bilby
  • leo.tsukada/bilby
  • will-farr/bilby
  • vijay.varma/bilby
  • jeremy.baier/bilby
  • joshua.brandt/bilby
  • ethan.payne/bilby
  • ka-lok.lo/bilby
  • antoni.ramos-buades/bilby
  • oliviastephany.wilk/bilby
  • jack.heinzel/bilby
  • samson.leong/bilby-psi4
  • viviana.caceres/bilby
  • nadia.qutob/bilby
  • michael-coughlin/bilby
  • hemantakumar.phurailatpam/bilby
  • boris.goncharov/bilby
  • sama.al-shammari/bilby
  • siqi.zhong/bilby
  • jocelyn-read/bilby
  • marc.penuliar/bilby
  • stephanie.letourneau/bilby
  • alexandresebastien.goettel/bilby
  • alec.gunny/bilby
  • serguei.ossokine/bilby
  • pratyusava.baral/bilby
  • sophie.hourihane/bilby
  • eunsub/bilby
  • james.hart/bilby
  • pratyusava.baral/bilby-tg
  • zhaozc/bilby
  • pratyusava.baral/bilby_SoG
  • tomasz.baka/bilby
  • nicogerardo.bers/bilby
  • soumen.roy/bilby
  • isaac.mcmahon/healpix-redundancy
  • asamakai.baker/bilby-frequency-dependent-antenna-pattern-functions
  • anna.puecher/bilby
  • pratyusava.baral/bilby-x-g
  • thibeau.wouters/bilby
  • christian.adamcewicz/bilby
  • raffi.enficiaud/bilby
109 results
Show changes
Commits on Source (8)
......@@ -13,4 +13,5 @@ MANIFEST
*.dat
*.version
*.ipynb_checkpoints
outdir/*
\ No newline at end of file
outdir/*
.idea/*
......@@ -3,7 +3,6 @@ from __future__ import division
import re
from importlib import import_module
import os
from collections import OrderedDict
from future.utils import iteritems
import json
from io import open as ioopen
......@@ -24,7 +23,7 @@ from .utils import (
)
class PriorDict(OrderedDict):
class PriorDict(dict):
def __init__(self, dictionary=None, filename=None,
conversion_function=None):
""" A set of priors
......@@ -472,7 +471,7 @@ class PriorDict(OrderedDict):
We have to overwrite the copy method as it fails due to the presence of
defaults.
"""
return self.__class__(dictionary=OrderedDict(self))
return self.__class__(dictionary=dict(self))
class PriorSet(PriorDict):
......@@ -777,7 +776,7 @@ class Prior(object):
dict_with_properties = self.__dict__.copy()
for key in property_names:
dict_with_properties[key] = getattr(self, key)
instantiation_dict = OrderedDict()
instantiation_dict = dict()
for key in subclass_args:
instantiation_dict[key] = dict_with_properties[key]
return instantiation_dict
......@@ -1238,12 +1237,19 @@ class SymmetricLogUniform(Prior):
Union[float, array_like]: Rescaled probability
"""
self.test_valid_for_rescaling(val)
if val < 0.5:
return -self.maximum * np.exp(-2 * val * np.log(self.maximum / self.minimum))
elif val > 0.5:
return self.minimum * np.exp(np.log(self.maximum / self.minimum) * (2 * val - 1))
if isinstance(val, (float, int)):
if val < 0.5:
return -self.maximum * np.exp(-2 * val * np.log(self.maximum / self.minimum))
else:
return self.minimum * np.exp(np.log(self.maximum / self.minimum) * (2 * val - 1))
else:
raise ValueError("Rescale not valid for val=0.5")
vals_less_than_5 = val < 0.5
rescaled = np.empty_like(val)
rescaled[vals_less_than_5] = -self.maximum * np.exp(-2 * val[vals_less_than_5] *
np.log(self.maximum / self.minimum))
rescaled[~vals_less_than_5] = self.minimum * np.exp(np.log(self.maximum / self.minimum) *
(2 * val[~vals_less_than_5] - 1))
return rescaled
def prob(self, val):
"""Return the prior probability of val
......@@ -2677,11 +2683,11 @@ class MultivariateGaussianDist(object):
self.add_mode(mu, sigma, corrcoef, cov, weight)
# a dictionary of the parameters as requested by the prior
self.requested_parameters = OrderedDict()
self.requested_parameters = dict()
self.reset_request()
# a dictionary of the rescaled parameters
self.rescale_parameters = OrderedDict()
self.rescale_parameters = dict()
self.reset_rescale()
# a list of sampled parameters
......@@ -2977,7 +2983,7 @@ class MultivariateGaussianDist(object):
dict_with_properties = self.__dict__.copy()
for key in property_names:
dict_with_properties[key] = getattr(self, key)
instantiation_dict = OrderedDict()
instantiation_dict = dict()
for key in subclass_args:
if isinstance(dict_with_properties[key], list):
value = np.asarray(dict_with_properties[key]).tolist()
......
......@@ -22,7 +22,7 @@ from ..core.utils import (
speed_of_light, radius_of_earth)
from ..core.prior import Interped, Prior, Uniform
from .detector import InterferometerList
from .prior import BBHPriorDict
from .prior import BBHPriorDict, CBCPriorDict
from .source import lal_binary_black_hole
from .utils import noise_weighted_inner_product, build_roq_weights, blockwise_dot_product
from .waveform_generator import WaveformGenerator
......@@ -824,6 +824,12 @@ class ROQGravitationalWaveTransient(GravitationalWaveTransient):
quadratic_matrix array, or the array itself.
roq_params: str, array_like
Parameters describing the domain of validity of the ROQ basis.
roq_params_check: bool
If true, run tests using the roq_params to check the prior and data are
valid for the ROQ
roq_scale_factor: float
The ROQ scale factor used. WARNING: this does not apply the scaling,
but is only used for checking that the ROQ basis is appropriate.
priors: dict, bilby.prior.PriorDict
A dictionary of priors containing at least the geocent_time prior
distance_marginalization_lookup_table: (dict, str), optional
......@@ -838,7 +844,7 @@ class ROQGravitationalWaveTransient(GravitationalWaveTransient):
"""
def __init__(self, interferometers, waveform_generator, priors,
weights=None, linear_matrix=None, quadratic_matrix=None,
roq_params=None,
roq_params=None, roq_params_check=True, roq_scale_factor=1,
distance_marginalization=False, phase_marginalization=False,
distance_marginalization_lookup_table=None):
super(ROQGravitationalWaveTransient, self).__init__(
......@@ -850,9 +856,12 @@ class ROQGravitationalWaveTransient(GravitationalWaveTransient):
distance_marginalization_lookup_table=distance_marginalization_lookup_table,
jitter_time=False)
self.roq_params_check = roq_params_check
self.roq_scale_factor = roq_scale_factor
if isinstance(roq_params, np.ndarray) or roq_params is None:
self.roq_params = roq_params
elif isinstance(roq_params, str):
self.roq_params_file = roq_params
self.roq_params = np.genfromtxt(roq_params, names=True)
else:
raise TypeError("roq_params should be array or str")
......@@ -968,6 +977,75 @@ class ROQGravitationalWaveTransient(GravitationalWaveTransient):
in_bounds = (indices[0] >= 0) & (indices[-1] < samples.size)
return indices, in_bounds
def perform_roq_params_check(self, ifo=None):
""" Perform checking that the prior and data are valid for the ROQ
Parameters
----------
ifo: bilby.gw.detector.Interferometer
The interferometer
"""
if self.roq_params_check is False:
logger.warning("No ROQ params checking performed")
return
else:
if getattr(self, "roq_params_file", None) is not None:
msg = ("Check ROQ params {} with roq_scale_factor={}"
.format(self.roq_params_file, self.roq_scale_factor))
else:
msg = ("Check ROQ params with roq_scale_factor={}"
.format(self.roq_scale_factor))
logger.info(msg)
roq_params = self.roq_params
roq_params['flow'] *= self.roq_scale_factor
roq_params['fhigh'] *= self.roq_scale_factor
roq_params['seglen'] /= self.roq_scale_factor
roq_params['chirpmassmin'] /= self.roq_scale_factor
roq_params['chirpmassmax'] /= self.roq_scale_factor
roq_params['compmin'] /= self.roq_scale_factor
if ifo.maximum_frequency > roq_params['fhigh']:
raise BilbyROQParamsRangeError(
"Requested maximum frequency {} larger than ROQ basis fhigh {}"
.format(ifo.maximum_frequency, roq_params['fhigh']))
if ifo.minimum_frequency < roq_params['flow']:
raise BilbyROQParamsRangeError(
"Requested minimum frequency {} lower than ROQ basis flow {}"
.format(ifo.minimum_frequency, roq_params['flow']))
if ifo.strain_data.duration != roq_params['seglen']:
raise BilbyROQParamsRangeError(
"Requested duration differs from ROQ basis seglen")
priors = self.priors
if isinstance(priors, CBCPriorDict) is False:
logger.warning("Unable to check ROQ parameter bounds: priors not understood")
return
if priors.minimum_chirp_mass is None:
logger.warning("Unable to check minimum chirp mass ROQ bounds")
elif priors.minimum_chirp_mass < roq_params["chirpmassmin"]:
raise BilbyROQParamsRangeError(
"Prior minimum chirp mass {} less than ROQ basis bound {}"
.format(priors.minimum_chirp_mass,
roq_params["chirpmassmin"]))
if priors.maximum_chirp_mass is None:
logger.warning("Unable to check maximum_chirp mass ROQ bounds")
elif priors.maximum_chirp_mass > roq_params["chirpmassmax"]:
raise BilbyROQParamsRangeError(
"Prior maximum chirp mass {} greater than ROQ basis bound {}"
.format(priors.maximum_chirp_mass,
roq_params["chirpmassmax"]))
if priors.minimum_component_mass is None:
logger.warning("Unable to check minimum component mass ROQ bounds")
elif priors.minimum_component_mass < roq_params["compmin"]:
raise BilbyROQParamsRangeError(
"Prior minimum component mass {} less than ROQ basis bound {}"
.format(priors.minimum_component_mass,
roq_params["compmin"]))
def _set_weights(self, linear_matrix, quadratic_matrix):
""" Setup the time-dependent ROQ weights.
......@@ -991,8 +1069,7 @@ class ROQGravitationalWaveTransient(GravitationalWaveTransient):
for ifo in self.interferometers:
if self.roq_params is not None:
if ifo.maximum_frequency > self.roq_params['fhigh']:
raise ValueError("Requested maximum frequency larger than ROQ basis fhigh")
self.perform_roq_params_check(ifo)
# Generate frequencies for the ROQ
roq_frequencies = create_frequency_series(
sampling_frequency=self.roq_params['fhigh'] * 2,
......@@ -1167,3 +1244,7 @@ def get_binary_black_hole_likelihood(interferometers):
waveform_arguments={'waveform_approximant': 'IMRPhenomPv2',
'reference_frequency': 50})
return GravitationalWaveTransient(interferometers, waveform_generator)
class BilbyROQParamsRangeError(Exception):
pass
import os
import copy
import numpy as np
from scipy.interpolate import InterpolatedUnivariateSpline
......@@ -9,7 +10,9 @@ from ..core.utils import infer_args_from_method, logger
from .conversion import (
convert_to_lal_binary_black_hole_parameters,
convert_to_lal_binary_neutron_star_parameters, generate_mass_parameters,
generate_tidal_parameters, fill_from_fixed_priors)
generate_tidal_parameters, fill_from_fixed_priors,
chirp_mass_and_mass_ratio_to_total_mass,
total_mass_and_mass_ratio_to_component_masses)
from .cosmology import get_cosmology
try:
......@@ -19,6 +22,70 @@ except ImportError:
" not be able to use some of the prebuilt functions.")
class BilbyPriorConversionError(Exception):
pass
def convert_to_flat_in_component_mass_prior(result, fraction=0.25):
""" Converts samples flat in chirp-mass and mass-ratio to flat in component mass
Parameters
----------
result: bilby.core.result.Result
The output result complete with priors and posteriors
fraction: float [0, 1]
The fraction of samples to draw (default=0.25). Note, if too high a
fraction of samples are draw, the reweighting will not be applied in
effect.
"""
if getattr(result, "priors") is not None:
if isinstance(getattr(result.priors, "chirp_mass", None), Uniform) is False:
BilbyPriorConversionError("chirp mass prior should be Uniform")
if isinstance(getattr(result.priors, "mass_ratio", None), Uniform) is False:
BilbyPriorConversionError("mass_ratio prior should be Uniform")
if isinstance(getattr(result.priors, "mass_1", None), Constraint):
BilbyPriorConversionError("mass_1 prior should be a Constraint")
if isinstance(getattr(result.priors, "mass_2", None), Constraint):
BilbyPriorConversionError("mass_2 prior should be a Constraint")
else:
BilbyPriorConversionError("No prior in the result: unable to convert")
result = copy.copy(result)
priors = result.priors
posterior = result.posterior
priors["chirp_mass"] = Constraint(
priors["chirp_mass"].minimum, priors["chirp_mass"].maximum,
"chirp_mass", latex_label=priors["chirp_mass"].latex_label)
priors["mass_ratio"] = Constraint(
priors["mass_ratio"].minimum, priors["mass_ratio"].maximum,
"mass_ratio", latex_label=priors["mass_ratio"].latex_label)
priors["mass_1"] = Uniform(
priors["mass_1"].minimum, priors["mass_1"].maximum, "mass_1",
latex_label=priors["mass_1"].latex_label)
priors["mass_1"] = Uniform(
priors["mass_2"].minimum, priors["mass_2"].maximum, "mass_2",
latex_label=priors["mass_2"].latex_label)
weights = posterior["mass_1"] ** 2 / posterior["chirp_mass"]
result.posterior = posterior.sample(frac=fraction, weights=weights)
logger.info("Resampling posterior to flat-in-component mass")
effective_sample_size = sum(weights)**2 / sum(weights**2)
n_posterior = len(posterior)
if fraction > effective_sample_size / n_posterior:
logger.warning(
"Sampling posterior of length {} with fraction {}, but "
"effective_sample_size / len(posterior) = {}. This may produce "
"biased results"
.format(n_posterior, fraction, effective_sample_size / n_posterior)
)
result.posterior = posterior.sample(frac=fraction, weights=weights, replace=True)
result.meta_data["reweighted_to_flat_in_component_mass"] = True
return result
class Cosmological(Interped):
@property
......@@ -240,7 +307,61 @@ class AlignedSpin(Interped):
boundary=boundary)
class BBHPriorDict(PriorDict):
class CBCPriorDict(PriorDict):
@property
def minimum_chirp_mass(self):
mass_1 = None
mass_2 = None
if "chirp_mass" in self:
return self["chirp_mass"].minimum
elif "mass_1" in self:
mass_1 = self['mass_1'].minimum
if "mass_2" in self:
mass_2 = self['mass_2'].minimum
elif "mass_ratio" in self:
mass_2 = mass_1 * self["mass_ratio"].minimum
if mass_1 is not None and mass_2 is not None:
s = generate_mass_parameters(dict(mass_1=mass_1, mass_2=mass_2))
return s["chirp_mass"]
else:
logger.warning("Unable to determine minimum chirp mass")
return None
@property
def maximum_chirp_mass(self):
mass_1 = None
mass_2 = None
if "chirp_mass" in self:
return self["chirp_mass"].maximum
elif "mass_1" in self:
mass_1 = self['mass_1'].maximum
if "mass_2" in self:
mass_2 = self['mass_2'].maximum
elif "mass_ratio" in self:
mass_2 = mass_1 * self["mass_ratio"].maximum
if mass_1 is not None and mass_2 is not None:
s = generate_mass_parameters(dict(mass_1=mass_1, mass_2=mass_2))
return s["chirp_mass"]
else:
logger.warning("Unable to determine maximum chirp mass")
return None
@property
def minimum_component_mass(self):
if "mass_2" in self:
return self["mass_2"].minimum
if "chirp_mass" in self and "mass_ratio" in self:
total_mass = chirp_mass_and_mass_ratio_to_total_mass(
self["chirp_mass"].minimum, self["mass_ratio"].minimum)
_, mass_2 = total_mass_and_mass_ratio_to_component_masses(
self["mass_ratio"].minimum, total_mass)
return mass_2
else:
logger.warning("Unable to determine minimum component mass")
return None
class BBHPriorDict(CBCPriorDict):
def __init__(self, dictionary=None, filename=None, aligned_spin=False,
conversion_function=None):
""" Initialises a Prior set for Binary Black holes
......@@ -346,7 +467,7 @@ class BBHPriorDict(PriorDict):
return False
class BNSPriorDict(PriorDict):
class BNSPriorDict(CBCPriorDict):
def __init__(self, dictionary=None, filename=None, aligned_spin=True,
conversion_function=None):
......
......@@ -50,8 +50,7 @@ injection_parameters = dict(
phase=1.3, geocent_time=1126259642.413, ra=1.375, dec=-1.2108)
waveform_arguments = dict(waveform_approximant='IMRPhenomPv2',
reference_frequency=20. * scale_factor,
minimum_frequency=20. * scale_factor)
reference_frequency=20. * scale_factor)
waveform_generator = bilby.gw.WaveformGenerator(
duration=duration, sampling_frequency=sampling_frequency,
......@@ -65,6 +64,8 @@ ifos.set_strain_data_from_power_spectral_densities(
start_time=injection_parameters['geocent_time'] - 3)
ifos.inject_signal(waveform_generator=waveform_generator,
parameters=injection_parameters)
for ifo in ifos:
ifo.minimum_frequency = 20 * scale_factor
# make ROQ waveform generator
search_waveform_generator = bilby.gw.waveform_generator.WaveformGenerator(
......@@ -98,7 +99,7 @@ likelihood = bilby.gw.likelihood.ROQGravitationalWaveTransient(
priors=priors, roq_params=params)
# write the weights to file so they can be loaded multiple times
likelihood.save_weights('weights.json')
likelihood.save_weights('weights.npz')
# remove the basis matrices as these are big for longer bases
del basis_matrix_linear, basis_matrix_quadratic
......@@ -106,10 +107,10 @@ del basis_matrix_linear, basis_matrix_quadratic
# load the weights from the file
likelihood = bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=ifos, waveform_generator=search_waveform_generator,
weights='weights.json', priors=priors)
weights='weights.npz', priors=priors)
result = bilby.run_sampler(
likelihood=likelihood, priors=priors, sampler='pymultinest', npoints=500,
likelihood=likelihood, priors=priors, sampler='dynesty', npoints=500,
injection_parameters=injection_parameters, outdir=outdir, label=label)
# Make a corner plot.
......
from __future__ import division, absolute_import
import unittest
import bilby
import os
import numpy as np
import bilby
from bilby.gw.likelihood import BilbyROQParamsRangeError
class TestBasicGWTransient(unittest.TestCase):
......@@ -533,7 +536,18 @@ class TestROQLikelihood(unittest.TestCase):
self.duration = 4
self.sampling_frequency = 2048
roq_dir = '/roq_basis'
# Possible locations for the ROQ: in the docker image, local, or on CIT
trial_roq_paths = [
"/roq_basis",
os.path.join(os.path.expanduser("~"), 'ROQ_data/IMRPhenomPv2/4s'),
"/home/cbc/ROQ_data/IMRPhenomPv2/4s"]
roq_dir = None
for path in trial_roq_paths:
if os.path.isdir(path):
roq_dir = path
break
if roq_dir is None:
raise Exception("Unable to load ROQ basis: cannot proceed with tests")
linear_matrix_file = "{}/B_linear.npy".format(roq_dir)
quadratic_matrix_file = "{}/B_quadratic.npy".format(roq_dir)
......@@ -556,6 +570,11 @@ class TestROQLikelihood(unittest.TestCase):
sampling_frequency=self.sampling_frequency, duration=self.duration)
self.priors = bilby.gw.prior.BBHPriorDict()
self.priors.pop("mass_1")
self.priors.pop("mass_2")
# Testing is done with the 4s IMRPhenomPV2 ROQ basis
self.priors["chirp_mass"] = bilby.core.prior.Uniform(12.299703, 45)
self.priors["mass_ratio"] = bilby.core.prior.Uniform(0.125, 1)
self.priors['geocent_time'] = bilby.core.prior.Uniform(1.19, 1.21)
non_roq_wfg = bilby.gw.WaveformGenerator(
......@@ -637,8 +656,9 @@ class TestROQLikelihood(unittest.TestCase):
roq.log_likelihood_ratio(), self.roq.log_likelihood_ratio())
def test_create_roq_weights_frequency_mismatch_works_with_params(self):
self.ifos[0].maximum_frequency = self.ifos[0].maximum_frequency / 2
_ = bilby.gw.likelihood.ROQGravitationalWaveTransient(
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=self.ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file, roq_params=self.params_file,
quadratic_matrix=self.quadratic_matrix_file, priors=self.priors)
......@@ -646,11 +666,149 @@ class TestROQLikelihood(unittest.TestCase):
def test_create_roq_weights_frequency_mismatch_fails_without_params(self):
self.ifos[0].maximum_frequency = self.ifos[0].maximum_frequency / 2
with self.assertRaises(ValueError):
_ = bilby.gw.likelihood.ROQGravitationalWaveTransient(
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=self.ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file,
quadratic_matrix=self.quadratic_matrix_file, priors=self.priors)
def test_create_roq_weights_fails_with_min_chirp_mass_outside_bounds(self):
self.ifos[0].maximum_frequency = self.ifos[0].maximum_frequency / 2
self.priors["chirp_mass"] = bilby.core.prior.Uniform(10, 45)
with self.assertRaises(BilbyROQParamsRangeError):
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=self.ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file,
roq_params=self.params_file,
quadratic_matrix=self.quadratic_matrix_file,
priors=self.priors)
def test_create_roq_weights_fails_with_max_chirp_mass_outside_bounds(self):
self.ifos[0].maximum_frequency = self.ifos[0].maximum_frequency / 2
self.priors["chirp_mass"] = bilby.core.prior.Uniform(12.299703, 50)
with self.assertRaises(BilbyROQParamsRangeError):
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=self.ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file,
roq_params=self.params_file,
quadratic_matrix=self.quadratic_matrix_file,
priors=self.priors)
def test_create_roq_weights_fails_with_min_component_mass_outside_bounds(self):
self.ifos[0].maximum_frequency = self.ifos[0].maximum_frequency / 2
self.priors["chirp_mass"] = bilby.core.prior.Uniform(12.299703, 45)
self.priors["mass_ratio"] = bilby.core.prior.Uniform(1e-5, 1)
with self.assertRaises(BilbyROQParamsRangeError):
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=self.ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file,
roq_params=self.params_file,
quadratic_matrix=self.quadratic_matrix_file,
priors=self.priors)
def test_create_roq_weights_fails_with_max_frequency(self):
ifos = bilby.gw.detector.InterferometerList(['H1'])
ifos.set_strain_data_from_power_spectral_densities(
sampling_frequency=2**14, duration=4)
ifos[0].maximum_frequency = 2**13
with self.assertRaises(BilbyROQParamsRangeError):
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file,
roq_params=self.params_file,
quadratic_matrix=self.quadratic_matrix_file,
priors=self.priors)
def test_create_roq_weights_fails_due_to_min_frequency(self):
self.ifos[0].minimum_frequency = 15
with self.assertRaises(BilbyROQParamsRangeError):
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=self.ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file,
roq_params=self.params_file,
quadratic_matrix=self.quadratic_matrix_file,
priors=self.priors)
def test_create_roq_weights_fails_due_to_duration(self):
ifos = bilby.gw.detector.InterferometerList(['H1'])
ifos.set_strain_data_from_power_spectral_densities(
sampling_frequency=self.sampling_frequency, duration=16)
with self.assertRaises(BilbyROQParamsRangeError):
bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=ifos, waveform_generator=self.roq_wfg,
linear_matrix=self.linear_matrix_file,
roq_params=self.params_file,
quadratic_matrix=self.quadratic_matrix_file,
priors=self.priors)
class TestRescaledROQLikelihood(unittest.TestCase):
def test_rescaling(self):
# Possible locations for the ROQ: in the docker image, local, or on CIT
trial_roq_paths = [
"/roq_basis",
os.path.join(os.path.expanduser("~"), 'ROQ_data/IMRPhenomPv2/4s'),
"/home/cbc/ROQ_data/IMRPhenomPv2/4s"]
roq_dir = None
for path in trial_roq_paths:
if os.path.isdir(path):
roq_dir = path
break
if roq_dir is None:
raise Exception("Unable to load ROQ basis: cannot proceed with tests")
linear_matrix_file = "{}/B_linear.npy".format(roq_dir)
quadratic_matrix_file = "{}/B_quadratic.npy".format(roq_dir)
fnodes_linear_file = "{}/fnodes_linear.npy".format(roq_dir)
fnodes_linear = np.load(fnodes_linear_file).T
fnodes_quadratic_file = "{}/fnodes_quadratic.npy".format(roq_dir)
fnodes_quadratic = np.load(fnodes_quadratic_file).T
self.linear_matrix_file = "{}/B_linear.npy".format(roq_dir)
self.quadratic_matrix_file = "{}/B_quadratic.npy".format(roq_dir)
self.params_file = "{}/params.dat".format(roq_dir)
scale_factor = 0.5
params = np.genfromtxt(self.params_file, names=True)
params['flow'] *= scale_factor
params['fhigh'] *= scale_factor
params['seglen'] /= scale_factor
params['chirpmassmin'] /= scale_factor
params['chirpmassmax'] /= scale_factor
params['compmin'] /= scale_factor
self.duration = 4 / scale_factor
self.sampling_frequency = 2048 * scale_factor
ifos = bilby.gw.detector.InterferometerList(['H1'])
ifos.set_strain_data_from_power_spectral_densities(
sampling_frequency=self.sampling_frequency, duration=self.duration)
self.ifos = ifos
self.priors = bilby.gw.prior.BBHPriorDict()
self.priors.pop("mass_1")
self.priors.pop("mass_2")
# Testing is done with the 4s IMRPhenomPV2 ROQ basis
self.priors["chirp_mass"] = bilby.core.prior.Uniform(
12.299703 / scale_factor, 45 / scale_factor)
self.priors["mass_ratio"] = bilby.core.prior.Uniform(0.125, 1)
self.priors['geocent_time'] = bilby.core.prior.Uniform(1.19, 1.21)
self.roq_wfg = bilby.gw.waveform_generator.WaveformGenerator(
duration=self.duration, sampling_frequency=self.sampling_frequency,
frequency_domain_source_model=bilby.gw.source.roq,
waveform_arguments=dict(
frequency_nodes_linear=fnodes_linear,
frequency_nodes_quadratic=fnodes_quadratic,
reference_frequency=20., minimum_frequency=20.,
approximant='IMRPhenomPv2'))
self.roq = bilby.gw.likelihood.ROQGravitationalWaveTransient(
interferometers=ifos, waveform_generator=self.roq_wfg,
linear_matrix=linear_matrix_file, roq_params=params,
quadratic_matrix=quadratic_matrix_file, priors=self.priors)
class TestBBHLikelihoodSetUp(unittest.TestCase):
......
......@@ -3,11 +3,18 @@ from collections import OrderedDict
import unittest
import os
import sys
import pickle
import numpy as np
from astropy import cosmology
from scipy.stats import ks_2samp
import matplotlib.pyplot as plt
import pandas as pd
import bilby
from bilby.core.prior import Uniform, Constraint
from bilby.gw.prior import BBHPriorDict
from bilby.gw import conversion
class TestBBHPriorDict(unittest.TestCase):
......@@ -110,6 +117,77 @@ class TestBBHPriorDict(unittest.TestCase):
minimum=20, maximum=40, name='chirp_mass')
self.assertFalse(self.bbh_prior_dict.test_has_redundant_keys())
def test_pickle_prior(self):
priors = dict(chirp_mass=bilby.core.prior.Uniform(10, 20),
mass_ratio=bilby.core.prior.Uniform(0.125, 1))
priors = bilby.gw.prior.BBHPriorDict(priors)
with open("test.pickle", "wb") as file:
pickle.dump(priors, file)
with open("test.pickle", "rb") as file:
priors_loaded = pickle.load(file)
self.assertEqual(priors, priors_loaded)
class TestPriorConversion(unittest.TestCase):
def test_bilby_to_lalinference(self):
mass_1 = [1, 20]
mass_2 = [1, 20]
chirp_mass = [1, 5]
mass_ratio = [0.125, 1]
bilby_prior = BBHPriorDict(dictionary=dict(
chirp_mass=Uniform(name='chirp_mass', minimum=chirp_mass[0], maximum=chirp_mass[1]),
mass_ratio=Uniform(name='mass_ratio', minimum=mass_ratio[0], maximum=mass_ratio[1]),
mass_2=Constraint(name='mass_2', minimum=mass_1[0], maximum=mass_1[1]),
mass_1=Constraint(name='mass_1', minimum=mass_2[0], maximum=mass_2[1])))
lalinf_prior = BBHPriorDict(dictionary=dict(
chirp_mass=Constraint(name='chirp_mass', minimum=chirp_mass[0], maximum=chirp_mass[1]),
mass_2=Uniform(name='mass_2', minimum=mass_1[0], maximum=mass_1[1]),
mass_1=Uniform(name='mass_1', minimum=mass_2[0], maximum=mass_2[1])))
nsamples = 5000
bilby_samples = bilby_prior.sample(nsamples)
bilby_samples, _ = conversion.convert_to_lal_binary_black_hole_parameters(
bilby_samples)
# Quicker way to generate LA prior samples (rather than specifying Constraint)
lalinf_samples = []
while len(lalinf_samples) < nsamples:
s = lalinf_prior.sample()
if s["mass_1"] < s["mass_2"]:
s["mass_1"], s["mass_2"] = s["mass_2"], s["mass_1"]
if s["mass_2"] / s["mass_1"] > 0.125:
lalinf_samples.append(s)
lalinf_samples = pd.DataFrame(lalinf_samples)
lalinf_samples["mass_ratio"] = lalinf_samples["mass_2"] / lalinf_samples["mass_1"]
# Construct fake result object
result = bilby.core.result.Result()
result.search_parameter_keys = ["mass_ratio", "chirp_mass"]
result.meta_data = dict()
result.priors = bilby_prior
result.posterior = pd.DataFrame(bilby_samples)
result_converted = bilby.gw.prior.convert_to_flat_in_component_mass_prior(result)
if "plot" in sys.argv:
# Useful for debugging
plt.hist(bilby_samples["mass_ratio"], bins=50, density=True, alpha=0.5)
plt.hist(result_converted.posterior["mass_ratio"], bins=50, density=True, alpha=0.5)
plt.hist(lalinf_samples["mass_ratio"], bins=50, alpha=0.5, density=True)
plt.show()
# Check that the non-reweighted posteriors fail a KS test
ks = ks_2samp(bilby_samples["mass_ratio"], lalinf_samples["mass_ratio"])
print("Non-reweighted KS test = ", ks)
self.assertFalse(ks.pvalue > 0.05)
# Check that the non-reweighted posteriors pass a KS test
ks = ks_2samp(result_converted.posterior["mass_ratio"], lalinf_samples["mass_ratio"])
print("Reweighted KS test = ", ks)
self.assertTrue(ks.pvalue > 0.001)
class TestPackagedPriors(unittest.TestCase):
""" Test that the prepackaged priors load """
......
......@@ -274,6 +274,16 @@ class TestPriorClasses(unittest.TestCase):
# the prob and ln_prob functions, it must be ignored in this test.
self.assertAlmostEqual(np.log(prior.prob(sample)), prior.ln_prob(sample), 12)
def test_many_prob_and_many_ln_prob(self):
for prior in self.priors:
samples = prior.sample(10)
if not isinstance(prior, bilby.core.prior.MultivariateGaussian):
ln_probs = prior.ln_prob(samples)
probs = prior.prob(samples)
for sample, logp, p in zip(samples, ln_probs, probs):
self.assertAlmostEqual(prior.ln_prob(sample), logp)
self.assertAlmostEqual(prior.prob(sample), p)
def test_cdf_is_inverse_of_rescaling(self):
domain = np.linspace(0, 1, 100)
threshold = 1e-9
......@@ -658,8 +668,8 @@ class TestPriorDict(unittest.TestCase):
priors_set = bilby.core.prior.PriorSet(self.priors)
self.assertEqual(priors_dict, priors_set)
def test_prior_set_is_ordered_dict(self):
self.assertIsInstance(self.prior_set_from_dict, OrderedDict)
def test_prior_set_is_dict(self):
self.assertIsInstance(self.prior_set_from_dict, dict)
def test_prior_set_has_correct_length(self):
self.assertEqual(3, len(self.prior_set_from_dict))
......