Commit 40e0c291 authored by Sylvia Biscoveanu's avatar Sylvia Biscoveanu Committed by Gregory Ashton
Browse files

Add method to get data by channel name

parent 709df9e9
......@@ -233,7 +233,13 @@ def load_data_from_cache_file(
psd_set = False
with open(cache_file, 'r') as ff:
for line in ff:
lines = ff.readlines()
if len(lines)>1:
raise ValueError('This method cannot handle cache files with'
' multiple frames. Use `load_data_by_channel_name'
' instead.')
else:
line = lines[0]
cache = lal.utils.cache.CacheEntry(line)
data_in_cache = (
(cache.segment[0].gpsSeconds < start_time) &
......@@ -243,7 +249,13 @@ def load_data_from_cache_file(
(cache.segment[1].gpsSeconds > psd_start_time + psd_duration))
ifo = get_empty_interferometer(
"{}1".format(cache.observatory))
if not data_set & data_in_cache:
if not data_in_cache:
raise ValueError('The specified data segment does not exist in'
' this frame.')
if not psd_in_cache:
raise ValueError('The specified PSD data segment does not exist'
' in this frame.')
if (not data_set) & data_in_cache:
ifo.set_strain_data_from_frame_file(
frame_file=cache.path,
sampling_frequency=sampling_frequency,
......@@ -251,7 +263,7 @@ def load_data_from_cache_file(
start_time=start_time,
channel=channel_name, buffer_time=0)
data_set = True
if not psd_set & psd_in_cache:
if (not psd_set) & psd_in_cache:
ifo.power_spectral_density = \
PowerSpectralDensity.from_frame_file(
cache.path,
......@@ -272,3 +284,64 @@ def load_data_from_cache_file(
raise ValueError('Data not loaded for {}'.format(ifo.name))
elif not psd_set:
raise ValueError('PSD not created for {}'.format(ifo.name))
def load_data_by_channel_name(
channel_name, start_time, segment_duration, psd_duration, psd_start_time,
sampling_frequency=4096, roll_off=0.2,
overlap=0, outdir=None):
""" Helper routine to generate an interferometer from a channel name
This function creates an empty interferometer specified in the name
of the channel. It calls `ifo.set_strain_data_from_channel_name` to
set the data and PSD in the interferometer using data retrieved from
the specified channel using gwpy.TimeSeries.get()
Parameters
----------
channel_name: str
Channel name with the format `IFO:Channel`
start_time, psd_start_time: float
GPS start time of the segment and data stretch used for the PSD
segment_duration, psd_duration: float
Segment duration and duration of data to use to generate the PSD (in
seconds).
roll_off: float, optional
Rise time in seconds of tukey window.
overlap: float,
Number of seconds of overlap between FFTs.
sampling_frequency: int
Sampling frequency
outdir: str, optional
The output directory in which the data is saved
Returns
-------
ifo: bilby.gw.detector.Interferometer
An initialised interferometer object with strain data set to the
appropriate data fetched from the specified channel and a PSD.
"""
try:
det = channel_name.split(':')[-2]
except IndexError:
raise IndexError("Channel name must be of the format `IFO:Channel`")
ifo = get_empty_interferometer(det)
ifo.set_strain_data_from_channel_name(
channel = channel_name,
sampling_frequency=sampling_frequency,
duration=segment_duration,
start_time=start_time)
ifo.power_spectral_density = \
PowerSpectralDensity.from_channel_name(
channel=channel_name,
psd_start_time=psd_start_time,
psd_duration=psd_duration,
fft_length=segment_duration,
sampling_frequency=sampling_frequency,
roll_off=roll_off,
overlap=overlap,
name=det,
outdir=outdir,
analysis_segment_start_time=start_time)
return ifo
......@@ -187,6 +187,28 @@ class Interferometer(object):
duration=duration, start_time=start_time,
channel=channel, buffer_time=buffer_time)
def set_strain_data_from_channel_name(
self, channel, sampling_frequency, duration, start_time=0):
"""
Set the `Interferometer.strain_data` by fetching from given channel
using strain_data.set_from_channel_name()
Parameters
----------
channel: str
Channel to look for using gwpy in the format `IFO:Channel`
sampling_frequency: float
The sampling frequency (in Hz)
duration: float
The data duration (in s)
start_time: float
The GPS start-time of the data
"""
self.strain_data.set_from_channel_name(
channel=channel, sampling_frequency=sampling_frequency,
duration=duration, start_time=start_time)
def set_strain_data_from_csv(self, filename):
""" Set the `Interferometer.strain_data` from a csv file
......
......@@ -140,6 +140,49 @@ class PowerSpectralDensity(object):
analysis_segment_start_time=analysis_segment_start_time)
return PowerSpectralDensity(frequency_array=frequency_array, psd_array=psd_array)
@staticmethod
def from_channel_name(channel, psd_start_time, psd_duration,
fft_length=4, sampling_frequency=4096, roll_off=0.2,
overlap=0, name=None, outdir=None,
analysis_segment_start_time=None):
""" Generate power spectral density from a given channel name
by loading data using `strain_data.set_from_channel_name`
Parameters
----------
psd_start_time: float
Beginning of segment to analyse.
psd_duration: float, optional
Duration of data (in seconds) to generate PSD from.
fft_length: float, optional
Number of seconds in a single fft.
sampling_frequency: float, optional
Sampling frequency for time series.
This is twice the maximum frequency.
roll_off: float, optional
Rise time in seconds of tukey window.
overlap: float,
Number of seconds of overlap between FFTs.
channel: str
Name of channel to use to generate PSD in the format
`IFO:Channel`
name, outdir: str, optional
Name (and outdir) of the detector for which a PSD is to be
generated.
analysis_segment_start_time: float, optional
The start time of the analysis segment, if given, this data will
be removed before creating the PSD.
"""
strain = InterferometerStrainData(roll_off=roll_off)
strain.set_from_channel_name(
channel, duration=psd_duration, start_time=psd_start_time,
sampling_frequency=sampling_frequency)
frequency_array, psd_array = strain.create_power_spectral_density(
fft_length=fft_length, name=name, outdir=outdir, overlap=overlap,
analysis_segment_start_time=analysis_segment_start_time)
return PowerSpectralDensity(frequency_array=frequency_array, psd_array=psd_array)
@staticmethod
def from_amplitude_spectral_density_array(frequency_array, asd_array):
return PowerSpectralDensity(frequency_array=frequency_array, asd_array=asd_array)
......
......@@ -631,9 +631,9 @@ class InterferometerStrainData(object):
"""
self._times_and_frequencies = CoupledTimeAndFrequencySeries(duration=duration,
sampling_frequency=sampling_frequency,
start_time=start_time)
self._times_and_frequencies = CoupledTimeAndFrequencySeries(
duration=duration, sampling_frequency=sampling_frequency,
start_time=start_time)
logger.info('Reading data from frame file {}'.format(frame_file))
strain = gwutils.read_frame_file(
......@@ -642,3 +642,36 @@ class InterferometerStrainData(object):
resample=sampling_frequency)
self.set_from_gwpy_timeseries(strain)
def set_from_channel_name(self, channel, duration, start_time, sampling_frequency):
""" Set the `frequency_domain_strain` by fetching from given channel
using gwpy.TimesSeries.get(), which dynamically accesses either frames
on disk, or a remote NDS2 server to find and return data. This function
also verifies that the specified channel is given in the correct format.
Parameters
----------
channel: str
Channel to look for using gwpy in the format `IFO:Channel`
duration: float
The data duration (in s)
start_time: float
The GPS start-time of the data
sampling_frequency: float
The sampling frequency (in Hz)
"""
channel_comp = channel.split(':')
if len(channel_comp) != 2:
raise IndexError('Channel name must have format `IFO:Channel`')
self._times_and_frequencies = CoupledTimeAndFrequencySeries(
duration=duration, sampling_frequency=sampling_frequency,
start_time=start_time)
logger.info('Fetching data using channel {}'.format(channel))
strain = gwpy.timeseries.TimeSeries.get(
channel, start_time, start_time + duration)
strain = strain.resample(sampling_frequency)
self.set_from_gwpy_timeseries(strain)
......@@ -4,7 +4,7 @@
Transient gravitational wave data I/O
=====================================
This document describs how :code:`bilby` handles interferometer data and how
This document describes how :code:`bilby` handles interferometer data and how
you can load data.
What is used by the likelihood?
......@@ -67,6 +67,15 @@ To set the data from a frame file, use this method
.. automethod:: bilby.gw.detector.Interferometer.set_strain_data_from_frame_file
Setting the strain data from a channel name
===========================================
To set the data by specifying the channel name, use this method. It calls
:code:`gwpy.TimeSeries.get`, which dynamically accesses either frames on disk,
or a remote NDS2 server to find and return data.
.. automethod:: bilby.gw.detector.Interferometer.set_strain_data_from_channel_name
Setting the strain data to be Gaussian noise
============================================
......
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