Commit 64bb696f authored by plasky's avatar plasky

Merge branch 'master' of git.ligo.org:Monash/tupak

parents bf22e39d d8bc325a
Pipeline #29854 passed with stage
in 5 minutes and 42 seconds
.coverage
build/
dist/
docs/_*
tupak.egg-info/
MANIFEST
*.pyc
*.png
*.h5
*.h5.old
*.txt
*.log
*.dat
*.version
*.ipynb_checkpoints
outdir/*
\ No newline at end of file
......@@ -31,6 +31,17 @@ Changes currently on master, but not under a tag.
- Clean up of `detectors.py`: adds an `InterferometerStrainData` to handle strain data and `InterferometerSet` to handle multiple interferometers. All data setting should primarily be done through the `Interferometer.set_strain_data..` methods.
- Fix the comments and units of `nfft` and `infft` and general improvement to documentation of data.
- Fixed a bug in create_time_series
- Enable marginalisation over calibration uncertainty in Inteferemeter data.
- Fixed the normalisation of the marginalised `GravtitationalWaveTransient` likelihood.
- Fixed a bug in the detector response.
- Specifying detectors by name from the default command line options has been removed.
- The prior on polarisation phase has been reduced to [0, pi].
- More prior distributions added.
- More samplers supported, pymc3
- More core likelihoods, Poisson, Student's-t
- Add support for eccentric BBH
- Result print function fixed
- Add snr functions as methods of `Interferometer`
## [0.2.0] 2018-06-17
......
astropy
lalsuite<=6.48.1.dev20180823
gwpy
theano
\ No newline at end of file
theano
This diff is collapsed.
......@@ -357,14 +357,18 @@ class Result(dict):
Function which adds in extra parameters to the data frame,
should take the data_frame, likelihood and prior as arguments.
"""
data_frame = pd.DataFrame(
self.samples, columns=self.search_parameter_keys)
data_frame['log_likelihood'] = getattr(self, 'log_likelihood_evaluations', np.nan)
if hasattr(self, 'posterior') is False:
data_frame = pd.DataFrame(
self.samples, columns=self.search_parameter_keys)
data_frame['log_likelihood'] = getattr(
self, 'log_likelihood_evaluations', np.nan)
# We save the samples in the posterior and remove the array of samples
del self.samples
else:
data_frame = self.posterior
if conversion_function is not None:
data_frame = conversion_function(data_frame, likelihood, priors)
self.posterior = data_frame
# We save the samples in the posterior and remove the array of samples
del self.samples
def construct_cbc_derived_parameters(self):
""" Construct widely used derived parameters of CBCs """
......@@ -377,7 +381,7 @@ class Result(dict):
self.posterior['chi_eff'] = (self.posterior.a_1 * np.cos(self.posterior.tilt_1)
+ self.posterior.q * self.posterior.a_2 * np.cos(self.posterior.tilt_2)) / (
1 + self.posterior.q)
self.posterior['chi_p'] = max(self.posterior.a_1 * np.sin(self.posterior.tilt_1),
self.posterior['chi_p'] = np.maximum(self.posterior.a_1 * np.sin(self.posterior.tilt_1),
(4 * self.posterior.q + 3) / (3 * self.posterior.q + 4) * self.posterior.q
* self.posterior.a_2 * np.sin(self.posterior.tilt_2))
......
......@@ -808,6 +808,80 @@ class Pymultinest(Sampler):
return self.result
class Cpnest(Sampler):
"""
https://github.com/johnveitch/cpnest
TODO:
- allow custom jump proposals to be specified, ideally by parameter name
- figure out how to resume from a previous run
"""
@property
def kwargs(self):
return self.__kwargs
@kwargs.setter
def kwargs(self, kwargs):
# Check if nlive was instead given by another name
if 'Nlive' not in kwargs:
for equiv in ['nlives', 'n_live_points', 'npoint', 'npoints',
'nlive']:
if equiv in kwargs:
kwargs['Nlive'] = kwargs.pop(equiv)
if 'seed' not in kwargs:
logger.warning('No seed provided, cpnest will use 1234.')
# Set some default values
self.__kwargs = dict(verbose=1, Nthreads=1, Nlive=250, maxmcmc=1000)
# Overwrite default values with user specified values
self.__kwargs.update(kwargs)
def _run_external_sampler(self):
cpnest = self.external_sampler
import cpnest.model
class Model(cpnest.model.Model):
""" A wrapper class to pass our log_likelihood into cpnest """
def __init__(self, names, bounds):
self.names = names
self.bounds = bounds
self._check_bounds()
@staticmethod
def log_likelihood(x):
theta = [x[n] for n in self.search_parameter_keys]
return self.log_likelihood(theta)
@staticmethod
def log_prior(x):
theta = [x[n] for n in self.search_parameter_keys]
return self.log_prior(theta)
def _check_bounds(self):
for bound in self.bounds:
if not all(np.isfinite(bound)):
raise ValueError(
'CPNest requires priors to have finite bounds.')
bounds = [[self.priors[key].minimum, self.priors[key].maximum]
for key in self.search_parameter_keys]
model = Model(self.search_parameter_keys, bounds)
out = cpnest.CPNest(model, output=self.outdir, **self.kwargs)
out.run()
if self.plot:
out.plot()
# Since the output is not just samples, but log_likelihood as well,
# we turn this into a dataframe here. The index [0] here may be wrong
self.result.posterior = pd.DataFrame(out.posterior_samples[0])
self.result.log_evidence = out.NS.state.logZ
self.result.log_evidence_err = np.nan
return self.result
class Emcee(Sampler):
""" https://github.com/dfm/emcee """
......
......@@ -73,7 +73,9 @@ class InterferometerList(list):
"""
for interferometer in self:
interferometer.set_strain_data_from_power_spectral_density(sampling_frequency, duration, start_time)
interferometer.set_strain_data_from_power_spectral_density(sampling_frequency=sampling_frequency,
duration=duration,
start_time=start_time)
def inject_signal(self, parameters=None, injection_polarizations=None, waveform_generator=None):
""" Inject a signal into noise in each of the three detectors.
......@@ -129,7 +131,7 @@ class InterferometerList(list):
The string labelling the data
"""
for interferometer in self:
interferometer.save_data(outdir, label)
interferometer.save_data(outdir=outdir, label=label)
def plot_data(self, signal=None, outdir='.', label=None):
if utils.command_line_args.test:
......@@ -397,15 +399,16 @@ class InterferometerStrainData(object):
self.alpha, self.roll_off))
# self.low_pass_filter()
window = self.time_domain_window()
frequency_domain_strain, self.frequency_array = utils.nfft(
self._frequency_domain_strain, self.frequency_array = utils.nfft(
self._time_domain_strain * window, self.sampling_frequency)
self._frequency_domain_strain = frequency_domain_strain
return self._frequency_domain_strain * self.frequency_mask
else:
raise ValueError("frequency domain strain data not yet set")
@frequency_domain_strain.setter
def frequency_domain_strain(self, frequency_domain_strain):
if not len(self.frequency_array) == len(frequency_domain_strain):
raise ValueError("The frequency_array and the set strain have different lengths")
self._frequency_domain_strain = frequency_domain_strain
def add_to_frequency_domain_strain(self, x):
......@@ -424,7 +427,7 @@ class InterferometerStrainData(object):
logger.info(
"Low pass filter frequency of {}Hz requested, this is equal"
" or greater than the Nyquist frequency so no filter applied"
.format(filter_freq))
.format(filter_freq))
return
logger.debug("Applying low pass filter with filter frequency {}".format(filter_freq))
......
......@@ -319,8 +319,10 @@ def get_open_strain_data(
Passed to `gwpy.timeseries.TimeSeries.fetch_open_data`
Returns
-----------
-------
strain: gwpy.timeseries.TimeSeries
The object containing the strain data. If the connection to the open-data server
fails, this function retruns `None`.
"""
filename = '{}/{}_{}_{}.txt'.format(outdir, name, start_time, end_time)
......@@ -336,9 +338,16 @@ def get_open_strain_data(
else:
logger.info('Fetching open data from {} to {} with buffer time {}'
.format(start_time, end_time, buffer_time))
strain = TimeSeries.fetch_open_data(name, start_time, end_time, **kwargs)
logger.info('Saving data to {}'.format(filename))
strain.write(filename)
try:
strain = TimeSeries.fetch_open_data(name, start_time, end_time, **kwargs)
logger.info('Saving cache of data to {}'.format(filename))
strain.write(filename)
except Exception as e:
logger.info("Unable to fetch open data, see debug for detailed info")
logger.info("Call to gwpy.timeseries.TimeSeries.fetch_open_data returned {}"
.format(e))
strain = None
return strain
......
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