Source code for pycbc.strain.gate

# Copyright (C) 2016 Collin Capano
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
""" Functions for applying gates to data.
"""

from scipy import linalg
from . import strain


def _gates_from_cli(opts, gate_opt):
    """Parses the given `gate_opt` into something understandable by
    `strain.gate_data`.
    """
    gates = {}
    if getattr(opts, gate_opt) is None:
        return gates
    for gate in getattr(opts, gate_opt):
        try:
            ifo, central_time, half_dur, taper_dur = gate.split(':')
            central_time = float(central_time)
            half_dur = float(half_dur)
            taper_dur = float(taper_dur)
        except ValueError:
            raise ValueError("--gate {} not formatted correctly; ".format(
                gate) + "see help")
        try:
            gates[ifo].append((central_time, half_dur, taper_dur))
        except KeyError:
            gates[ifo] = [(central_time, half_dur, taper_dur)]
    return gates


[docs] def gates_from_cli(opts): """Parses the --gate option into something understandable by `strain.gate_data`. """ return _gates_from_cli(opts, 'gate')
[docs] def psd_gates_from_cli(opts): """Parses the --psd-gate option into something understandable by `strain.gate_data`. """ return _gates_from_cli(opts, 'psd_gate')
[docs] def apply_gates_to_td(strain_dict, gates): """Applies the given dictionary of gates to the given dictionary of strain. Parameters ---------- strain_dict : dict Dictionary of time-domain strain, keyed by the ifos. gates : dict Dictionary of gates. Keys should be the ifo to apply the data to, values are a tuple giving the central time of the gate, the half duration, and the taper duration. Returns ------- dict Dictionary of time-domain strain with the gates applied. """ # copy data to new dictionary outdict = dict(strain_dict.items()) for ifo in gates: outdict[ifo] = strain.gate_data(outdict[ifo], gates[ifo]) return outdict
[docs] def apply_gates_to_fd(stilde_dict, gates): """Applies the given dictionary of gates to the given dictionary of strain in the frequency domain. Gates are applied by IFFT-ing the strain data to the time domain, applying the gate, then FFT-ing back to the frequency domain. Parameters ---------- stilde_dict : dict Dictionary of frequency-domain strain, keyed by the ifos. gates : dict Dictionary of gates. Keys should be the ifo to apply the data to, values are a tuple giving the central time of the gate, the half duration, and the taper duration. Returns ------- dict Dictionary of frequency-domain strain with the gates applied. """ # copy data to new dictionary outdict = dict(stilde_dict.items()) # create a time-domin strain dictionary to apply the gates to strain_dict = dict([[ifo, outdict[ifo].to_timeseries()] for ifo in gates]) # apply gates and fft back to the frequency domain for ifo,d in apply_gates_to_td(strain_dict, gates).items(): outdict[ifo] = d.to_frequencyseries() return outdict
[docs] def add_gate_option_group(parser): """Adds the options needed to apply gates to data. Parameters ---------- parser : object ArgumentParser instance. """ gate_group = parser.add_argument_group("Options for gating data") gate_group.add_argument("--gate", nargs="+", type=str, metavar="IFO:CENTRALTIME:HALFDUR:TAPERDUR", help="Apply one or more gates to the data before " "filtering.") gate_group.add_argument("--gate-overwhitened", action="store_true", help="Overwhiten data first, then apply the " "gates specified in --gate. Overwhitening " "allows for sharper tapers to be used, " "since lines are not blurred.") gate_group.add_argument("--psd-gate", nargs="+", type=str, metavar="IFO:CENTRALTIME:HALFDUR:TAPERDUR", help="Apply one or more gates to the data used " "for computing the PSD. Gates are applied " "prior to FFT-ing the data for PSD " "estimation.") return gate_group
[docs] def gate_and_paint(data, lindex, rindex, invpsd, copy=True): """Gates and in-paints data. Parameters ---------- data : TimeSeries The data to gate. lindex : int The start index of the gate. rindex : int The end index of the gate. invpsd : FrequencySeries The inverse of the PSD. copy : bool, optional Copy the data before applying the gate. Otherwise, the gate will be applied in-place. Default is True. Returns ------- TimeSeries : The gated and in-painted time series. """ # Uses the hole-filling method of # https://arxiv.org/pdf/1908.05644.pdf # Copy the data and zero inside the hole if copy: data = data.copy() # Here's ambiguity about when gate end time exactly is, rindex-1 or rindex? data[lindex:rindex] = 0 # get the over-whitened gated data tdfilter = invpsd.astype('complex').to_timeseries() * invpsd.delta_t owhgated_data = (data.to_frequencyseries() * invpsd).to_timeseries() # remove the projection into the null space proj = linalg.solve_toeplitz(tdfilter[:(rindex - lindex)], owhgated_data[lindex:rindex]) data[lindex:rindex] -= proj return data