Gitlab will migrate to a new storage backend starting 0300 UTC on 2020-04-04. We do not anticipate a maintenance window for this migration. Performance may be impacted over the weekend. Thanks for your patience.

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

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