def generate_short_inj_from_inj(self, inj_waveform, simulation_id):
     """Generate and a store a truncated representation of inj_waveform."""
     if not self.enabled or not self.match_threshold:
         # Do nothing!
         return
     if simulation_id in self.short_injections:
         err_msg = "An injection with simulation id "
         err_msg += str(simulation_id)
         err_msg += " has already been added. This suggests "
         err_msg += "that your injection file contains injections with "
         err_msg += "duplicate simulation_ids. This is not allowed."
         raise ValueError(err_msg)
     curr_length = len(inj_waveform)
     new_length = int(nearest_larger_binary_number(curr_length))
     # Don't want length less than 1/delta_f
     while new_length * inj_waveform.delta_t < 1. / self.coarsematch_deltaf:
         new_length = new_length * 2
     inj_waveform.resize(new_length)
     inj_tilde = inj_waveform.to_frequencyseries()
     # Dynamic range is important here!
     inj_tilde_np = inj_tilde.numpy() * DYN_RANGE_FAC
     delta_f = inj_tilde.get_delta_f()
     new_freq_len = int(self.coarsematch_fmax / delta_f + 1)
     # This shouldn't be a problem if injections are generated at
     # 16384 Hz ... It is only a problem of injection sample rate
     # gives a lower Nyquist than the trunc_f_max. If this error is
     # ever raised one could consider zero-padding the injection.
     assert (new_freq_len <= len(inj_tilde))
     df_ratio = int(self.coarsematch_deltaf / delta_f)
     inj_tilde_np = inj_tilde_np[:new_freq_len:df_ratio]
     new_inj = FrequencySeries(inj_tilde_np,
                               dtype=np.complex64,
                               delta_f=self.coarsematch_deltaf)
     self.short_injections[simulation_id] = new_inj
Beispiel #2
0
def get_td_waveform_from_fd(rwrap=0.2, **params):
    """ Return time domain version of fourier domain approximant.

    This returns a time domain version of a fourier domain approximant, with
    padding and tapering at the start of the waveform.

    Parameters
    ----------
    rwrap: float
        Cyclic time shift parameter in seconds. A fudge factor to ensure
        that the entire time series is contiguous in the array and not
        wrapped around the end.
    params: dict
        The parameters defining the waveform to generator.
        See `get_fd_waveform`.

    Returns
    -------
    hp: pycbc.types.TimeSeries
        Plus polarization time series
    hc: pycbc.types.TimeSeries
        Cross polarization time series
    """
    # determine the duration to use
    full_duration = duration = get_waveform_filter_length_in_time(**params)
    nparams = params.copy()

    while full_duration < duration * 1.5:
        full_duration = get_waveform_filter_length_in_time(**nparams)
        nparams['f_lower'] *= 0.99

    if 'f_ref' not in nparams:
        nparams['f_ref'] = params['f_lower']

    # factor to ensure the vectors are all large enough. We don't need to
    # completely trust our duration estimator in this case, at a small
    # increase in computational cost
    fudge_duration = (max(0, full_duration) + .1 + rwrap) * 1.5
    fsamples = int(fudge_duration / params['delta_t'])
    N = pnutils.nearest_larger_binary_number(fsamples)
    fudge_duration = N * params['delta_t']

    nparams['delta_f'] = 1.0 / fudge_duration
    hp, hc = get_fd_waveform(**nparams)

    # Resize to the right sample rate
    tsize = int(1.0 / params['delta_t'] /  nparams['delta_f'])
    fsize = tsize // 2 + 1
    hp.resize(fsize)
    hc.resize(fsize)

    # avoid wraparound
    hp = hp.cyclic_time_shift(-rwrap)
    hc = hc.cyclic_time_shift(-rwrap)

    hp = wfutils.fd_to_td(hp, left_window=(nparams['f_lower'],
                                           params['f_lower']))
    hc = wfutils.fd_to_td(hc, left_window=(nparams['f_lower'],
                                           params['f_lower']))
    return hp, hc
 def generate_short_inj_from_inj(self, inj_waveform, simulation_id):
     """Generate and a store a truncated representation of inj_waveform."""
     if not self.enabled:
         # Do nothing!
         return
     if simulation_id in self.short_injections:
         err_msg = "An injection with simulation id "
         err_msg += str(simulation_id)
         err_msg += " has already been added. This suggests "
         err_msg += "that your injection file contains injections with "
         err_msg += "duplicate simulation_ids. This is not allowed."
         raise ValueError(err_msg)
     curr_length = len(inj_waveform)
     new_length = int(nearest_larger_binary_number(curr_length))
     # Don't want length less than 1/delta_f
     while new_length * inj_waveform.delta_t < 1./self.coarsematch_deltaf:
         new_length = new_length * 2
     inj_waveform.resize(new_length)
     inj_tilde = inj_waveform.to_frequencyseries()
     # Dynamic range is important here!
     inj_tilde_np = inj_tilde.numpy() * DYN_RANGE_FAC
     delta_f = inj_tilde.get_delta_f()
     new_freq_len = int(self.coarsematch_fmax / delta_f + 1)
     # This shouldn't be a problem if injections are generated at
     # 16384 Hz ... It is only a problem of injection sample rate
     # gives a lower Nyquist than the trunc_f_max. If this error is
     # ever raised one could consider zero-padding the injection.
     assert(new_freq_len <= len(inj_tilde))
     df_ratio = int(self.coarsematch_deltaf/delta_f)
     inj_tilde_np = inj_tilde_np[:new_freq_len:df_ratio]
     new_inj = FrequencySeries(inj_tilde_np, dtype=np.complex64,
                               delta_f=self.coarsematch_deltaf)
     self.short_injections[simulation_id] = new_inj
Beispiel #4
0
def td_waveform_to_fd_waveform(waveform,
                               out=None,
                               length=None,
                               buffer_length=100):
    """ Convert a time domain into a frequency domain waveform by FFT.
        As a waveform is assumed to "wrap" in the time domain one must be
        careful to ensure the waveform goes to 0 at both "boundaries". To
        ensure this is done correctly the waveform must have the epoch set such
        the merger time is at t=0 and the length of the waveform should be
        shorter than the desired length of the FrequencySeries (times 2 - 1)
        so that zeroes can be suitably pre- and post-pended before FFTing.
        If given, out is a memory array to be used as the output of the FFT.
        If not given memory is allocated internally.
        If present the length of the returned FrequencySeries is determined
        from the length out. If out is not given the length can be provided
        expicitly, or it will be chosen as the nearest power of 2. If choosing
        length explicitly the waveform length + buffer_length is used when
        choosing the nearest binary number so that some zero padding is always
        added.
    """
    # Figure out lengths and set out if needed
    if out is None:
        if length is None:
            N = pnutils.nearest_larger_binary_number(len(waveform) + \
                                                     buffer_length)
            n = int(N // 2) + 1
        else:
            n = length
            N = (n - 1) * 2
        out = zeros(n, dtype=complex_same_precision_as(waveform))
    else:
        n = len(out)
        N = (n - 1) * 2
    delta_f = 1. / (N * waveform.delta_t)

    # total duration of the waveform
    tmplt_length = len(waveform) * waveform.delta_t
    if len(waveform) > N:
        err_msg = "The time domain template is longer than the intended "
        err_msg += "duration in the frequency domain. This situation is "
        err_msg += "not supported in this function. Please shorten the "
        err_msg += "waveform appropriately before calling this function or "
        err_msg += "increase the allowed waveform length. "
        err_msg += "Waveform length (in samples): {}".format(len(waveform))
        err_msg += ". Intended length: {}.".format(N)
        raise ValueError(err_msg)
    # for IMR templates the zero of time is at max amplitude (merger)
    # thus the start time is minus the duration of the template from
    # lower frequency cutoff to merger, i.e. minus the 'chirp time'
    tChirp = -float(waveform.start_time)  # conversion from LIGOTimeGPS
    waveform.resize(N)
    k_zero = int(waveform.start_time / waveform.delta_t)
    waveform.roll(k_zero)
    htilde = FrequencySeries(out, delta_f=delta_f, copy=False)
    fft(waveform.astype(real_same_precision_as(htilde)), htilde)
    htilde.length_in_time = tmplt_length
    htilde.chirp_length = tChirp
    return htilde
Beispiel #5
0
def get_td_waveform_from_fd(**params):
    """ Return time domain version of fourier domain approximant.

    This returns a time domain version of a fourier domain approximant, with
    padding and tapering at the start of the waveform.

    Parameters
    ----------
    params: dict
        The parameters defining the waveform to generator.
        See `get_fd_waveform`.

    Returns
    -------
    hp: pycbc.types.TimeSeries
        Plus polarization time series
    hc: pycbc.types.TimeSeries
        Cross polarization time series
    """

    # determine the duration to use
    full_duration = duration = get_waveform_filter_length_in_time(**params)
    nparams = params.copy()

    while full_duration < duration * 1.5:
        full_duration = get_waveform_filter_length_in_time(**nparams)
        nparams['f_lower'] -= 1

    if 'f_fref' not in nparams:
        nparams['f_ref'] = params['f_lower']

    # factor to ensure the vectors are all large enough. We don't need to
    # completely trust our duration estimator in this case, at a small
    # increase in computational cost
    rwrap = 0.2
    fudge_duration = (max(0, full_duration) + .1 + rwrap) * 1.5
    fsamples = int(fudge_duration / params['delta_t'])
    N = pnutils.nearest_larger_binary_number(fsamples)
    fudge_duration = N * params['delta_t']

    nparams['delta_f'] = 1.0 / fudge_duration
    hp, hc = get_fd_waveform(**nparams)

    # Resize to the right sample rate
    tsize = int(1.0 / params['delta_t'] /  nparams['delta_f'])
    fsize = tsize / 2 + 1
    hp.resize(fsize)
    hc.resize(fsize)

    # avoid wraparound
    hp = hp.cyclic_time_shift(-rwrap)
    hc = hc.cyclic_time_shift(-rwrap)

    hp = wfutils.fd_to_td(hp, left_window=(nparams['f_lower'],
                                           params['f_lower']))
    hc = wfutils.fd_to_td(hc, left_window=(nparams['f_lower'],
                                           params['f_lower']))
    return hp, hc
Beispiel #6
0
def td_waveform_to_fd_waveform(waveform, out=None, length=None,
                               buffer_length=100):
    """ Convert a time domain into a frequency domain waveform by FFT.
        As a waveform is assumed to "wrap" in the time domain one must be
        careful to ensure the waveform goes to 0 at both "boundaries". To
        ensure this is done correctly the waveform must have the epoch set such
        the merger time is at t=0 and the length of the waveform should be
        shorter than the desired length of the FrequencySeries (times 2 - 1)
        so that zeroes can be suitably pre- and post-pended before FFTing.
        If given, out is a memory array to be used as the output of the FFT.
        If not given memory is allocated internally.
        If present the length of the returned FrequencySeries is determined
        from the length out. If out is not given the length can be provided
        expicitly, or it will be chosen as the nearest power of 2. If choosing
        length explicitly the waveform length + buffer_length is used when
        choosing the nearest binary number so that some zero padding is always
        added.
    """
    # Figure out lengths and set out if needed
    if out is None:
        if length is None:
            N = pnutils.nearest_larger_binary_number(len(waveform) + \
                                                     buffer_length)
            n = int(N//2) + 1
        else:
            n = length
            N = (n-1)*2
        out = zeros(n, dtype=complex_same_precision_as(waveform))
    else:
        n = len(out)
        N = (n-1)*2
    delta_f =  1. / (N * waveform.delta_t)

    # total duration of the waveform
    tmplt_length = len(waveform) * waveform.delta_t
    if len(waveform) > N:
        err_msg = "The time domain template is longer than the intended "
        err_msg += "duration in the frequency domain. This situation is "
        err_msg += "not supported in this function. Please shorten the "
        err_msg += "waveform appropriately before calling this function or "
        err_msg += "increase the allowed waveform length. "
        err_msg += "Waveform length (in samples): {}".format(len(waveform))
        err_msg += ". Intended length: {}.".format(N)
        raise ValueError(err_msg)
    # for IMR templates the zero of time is at max amplitude (merger)
    # thus the start time is minus the duration of the template from
    # lower frequency cutoff to merger, i.e. minus the 'chirp time'
    tChirp = - float( waveform.start_time )  # conversion from LIGOTimeGPS
    waveform.resize(N)
    k_zero = int(waveform.start_time / waveform.delta_t)
    waveform.roll(k_zero)
    htilde = FrequencySeries(out, delta_f=delta_f, copy=False)
    fft(waveform.astype(real_same_precision_as(htilde)), htilde)
    htilde.length_in_time = tmplt_length
    htilde.chirp_length = tChirp
    return htilde
Beispiel #7
0
    def __getitem__(self, index):
        approximant = self.approximant(index)
        f_end = self.end_frequency(index)

        # Determine the length of time of the filter, rounded up to
        # nearest power of two
        min_buffer = 1.0 + self.minimum_buffer
    
        from pycbc.waveform.waveform import props
        buff_size = pycbc.waveform.get_waveform_filter_length_in_time(approximant, f_lower=self.f_lower, 
                                                                      **props(self.table[index]))
        tlen = nearest_larger_binary_number((buff_size + min_buffer) * self.sample_rate)
        flen = tlen / 2 + 1

        delta_f = self.sample_rate / float(tlen)

        if f_end is None or f_end >= (flen * delta_f):
            f_end = (flen-1) * delta_f

        logging.info("Generating %s, %ss, %i" % (approximant, 1.0/delta_f, index))

        # Get the waveform filter
        distance = 1.0 / DYN_RANGE_FAC
        htilde = pycbc.waveform.get_waveform_filter(
            zeros(flen, dtype=numpy.complex64), self.table[index],
            approximant=approximant, f_lower=self.f_lower, f_final=f_end,
            delta_f=delta_f, delta_t=1.0/self.sample_rate, distance=distance,
            **self.extra_args)

        # If available, record the total duration (which may
        # include ringdown) and the duration up to merger since they will be 
        # erased by the type conversion below.
        # NOTE: If these durations are not available the values in self.table
        #       will continue to take the values in the input file.
        if hasattr(htilde, 'length_in_time'):
            if htilde.length_in_time is not None:
                self.table[index].ttotal = htilde.length_in_time
        if hasattr(htilde, 'chirp_length'):
            if htilde.chirp_length is not None:
                self.table[index].template_duration = htilde.chirp_length

        htilde = htilde.astype(numpy.complex64)
        htilde.f_lower = self.f_lower
        htilde.end_frequency = f_end
        htilde.end_idx = int(htilde.end_frequency / htilde.delta_f)
        htilde.params = self.table[index]
        htilde.approximant = approximant
        htilde.chirp_length = htilde.params.template_duration
        htilde.length_in_time = htilde.params.ttotal
        
        # Add sigmasq as a method of this instance
        htilde.sigmasq = types.MethodType(sigma_cached, htilde)
        htilde._sigmasq = {}

        return htilde
Beispiel #8
0
def make_padded_frequency_series(vec, filter_N=None, delta_f=None):
    """Convert vec (TimeSeries or FrequencySeries) to a FrequencySeries. If
    filter_N and/or delta_f are given, the output will take those values. If
    not told otherwise the code will attempt to pad a timeseries first such that
    the waveform will not wraparound. However, if delta_f is specified to be
    shorter than the waveform length then wraparound *will* be allowed.
    """
    if filter_N is None:
        power = ceil(log(len(vec), 2)) + 1
        N = 2**power
    else:
        N = filter_N
    n = N / 2 + 1

    if isinstance(vec, FrequencySeries):
        vectilde = FrequencySeries(zeros(n,
                                         dtype=complex_same_precision_as(vec)),
                                   delta_f=1.0,
                                   copy=False)
        if len(vectilde) < len(vec):
            cplen = len(vectilde)
        else:
            cplen = len(vec)
        vectilde[0:cplen] = vec[0:cplen]
        delta_f = vec.delta_f

    elif isinstance(vec, TimeSeries):
        # First determine if the timeseries is too short for the specified df
        # and increase if necessary
        curr_length = len(vec)
        new_length = int(nearest_larger_binary_number(curr_length))
        while new_length * vec.delta_t < 1. / delta_f:
            new_length = new_length * 2
        vec.resize(new_length)
        # Then convert to frequencyseries
        v_tilde = vec.to_frequencyseries()
        # Then convert frequencyseries to required length and spacing by keeping
        # only every nth sample if delta_f needs increasing, and cutting at
        # Nyquist if the max frequency is too high.
        # NOTE: This assumes that the input and output data is using binary
        #       lengths.
        i_delta_f = v_tilde.get_delta_f()
        v_tilde = v_tilde.numpy()
        df_ratio = int(delta_f / i_delta_f)
        n_freq_len = int((n - 1) * df_ratio + 1)
        assert (n <= len(v_tilde))
        df_ratio = int(delta_f / i_delta_f)
        v_tilde = v_tilde[:n_freq_len:df_ratio]
        vectilde = FrequencySeries(v_tilde, delta_f=delta_f, dtype=complex128)

    return FrequencySeries(vectilde * DYN_RANGE_FAC,
                           delta_f=delta_f,
                           dtype=complex128)
Beispiel #9
0
def make_padded_frequency_series(vec, filter_N=None, delta_f=None):
    """Convert vec (TimeSeries or FrequencySeries) to a FrequencySeries. If
    filter_N and/or delta_f are given, the output will take those values. If
    not told otherwise the code will attempt to pad a timeseries first such that
    the waveform will not wraparound. However, if delta_f is specified to be
    shorter than the waveform length then wraparound *will* be allowed.
    """
    if filter_N is None:
        power = ceil(log(len(vec), 2)) + 1
        N = 2 ** power
    else:
        N = filter_N
    n = N / 2 + 1

    if isinstance(vec, FrequencySeries):
        vectilde = FrequencySeries(zeros(n, dtype=complex_same_precision_as(vec)),
                                   delta_f=1.0, copy=False)
        if len(vectilde) < len(vec):
            cplen = len(vectilde)
        else:
            cplen = len(vec)
        vectilde[0:cplen] = vec[0:cplen]
        delta_f = vec.delta_f

    elif isinstance(vec, TimeSeries):
        # First determine if the timeseries is too short for the specified df
        # and increase if necessary
        curr_length = len(vec)
        new_length = int(nearest_larger_binary_number(curr_length))
        while new_length * vec.delta_t < 1./delta_f:
            new_length = new_length * 2
        vec.resize(new_length)
        # Then convert to frequencyseries
        v_tilde = vec.to_frequencyseries()
        # Then convert frequencyseries to required length and spacing by keeping
        # only every nth sample if delta_f needs increasing, and cutting at
        # Nyquist if the max frequency is too high.
        # NOTE: This assumes that the input and output data is using binary
        #       lengths.
        i_delta_f = v_tilde.get_delta_f()
        v_tilde = v_tilde.numpy()
        df_ratio = int(delta_f / i_delta_f)
        n_freq_len = int((n-1) * df_ratio +1)
        assert(n <= len(v_tilde))
        df_ratio = int(delta_f / i_delta_f)
        v_tilde = v_tilde[:n_freq_len:df_ratio]
        vectilde = FrequencySeries(v_tilde, delta_f=delta_f, dtype=complex128)

    return FrequencySeries(vectilde * DYN_RANGE_FAC, delta_f=delta_f,
                           dtype=complex128)
Beispiel #10
0
def make_padded_frequency_series(vec, filter_N=None, delta_f=None):
    """
Convert vec (TimeSeries or FrequencySeries) to a FrequencySeries. For
a TimeSeries input, first it is resized to filter_N and  is  If
filter_N and/or delta_f are given, the output will take those values. If
    not told otherwise the code will attempt to pad a timeseries first such that
    the waveform will not wraparound. However, if delta_f is specified to be
    shorter than the waveform length then wraparound *will* be allowed.
    """
    # {{{
    if filter_N is None:
        filter_N = nearest_larger_binary_number(len(vec))
    filter_n = filter_N / 2 + 1

    if isinstance(vec, FrequencySeries):
        vectilde = FrequencySeries(zeros(filter_n),
                                   delta_f=vec.get_delta_f(),
                                   dtype=complex_same_precision_as(vec))
        cplen = min(len(vec), len(vectilde))
        vectilde[:cplen] = vec[:cplen]
        if delta_f is not None:
            delta_f_ratio = max(1, int(ceil(vectilde.get_delta_f() / delta_f)))
            vectilde = vectilde[:len(vectilde):delta_f_ratio]
    elif isinstance(vec, TimeSeries):
        delta_f_from_filter_N = 1. / filter_N / vec.get_delta_t()
        vec.resize(filter_N)
        v_tilde = vec.to_frequencyseries()
        vectilde = FrequencySeries(v_tilde[:],
                                   delta_f=delta_f_from_filter_N,
                                   dtype=complex_same_precision_as(vec),
                                   copy=True)
    else:
        vectilde = None
        raise IOError("Input is neither a TimeSeries nor a FrequencySeries")

    return vectilde
Beispiel #11
0
def get_chirp_time_region(trigger_params,
                          psd,
                          miss_match,
                          f_lower=30.,
                          f_max=2048.,
                          f_ref=30.):
    central_param = copy.deepcopy(trigger_params)
    # if central_param['approximant'] == 'SPAtmplt':
    central_param['approximant'] == 'TaylorF2RedSpin'
    # if not ('tau0' and 'tau3' in central_param):
    #     t0, t3 = pnu.mass1_mass2_to_tau0_tau3(central_param['mass1'], central_param['mass2'], f_ref)
    # else:
    #     t0 = central_param['tau0']
    #     t3 = central_param['tau3']
    # for tau0 boundary
    newt0, newt3 = temp_tau0_tau3_with_valid_dtau0(central_param['tau0'],
                                                   central_param['tau3'],
                                                   f_ref)
    temp_param0 = temp_param_from_central_param(central_param, newt0, newt3,
                                                f_ref)
    # for tau3 boundary
    newt0, newt3 = temp_tau0_tau3_with_valid_dtau3(central_param['tau0'],
                                                   central_param['tau3'],
                                                   f_ref)
    temp_param3 = temp_param_from_central_param(central_param, newt0, newt3,
                                                f_ref)

    tlen = pnu.nearest_larger_binary_number(
        max([central_param['tau0'], temp_param0['tau0'], temp_param3['tau0']]))
    df = 1.0 / tlen
    flen = int(f_max / df) + 1

    # hp = pt.zeros(flen, dtype=pt.complex64)
    # hp0 = pt.zeros(flen, dtype=pt.complex64)
    # hp3 = pt.zeros(flen, dtype=pt.complex64)

    # print central_param['approximant']

    # if central_param['approximant'] == 'SPAtmplt':
    #     central_param['approximant'] == 'TaylorF2RedSpin'
    # hp = pw.get_waveform_filter(hp, central_param, delta_f=df, f_lower=f_lower, f_ref=f_ref, f_final=f_max)
    # hp0 = pw.get_waveform_filter(hp0, temp_param0, delta_f=df, f_lower=f_lower, f_ref=f_ref, f_final=f_max)
    # hp3 = pw.get_waveform_filter(hp3, temp_param3, delta_f=df, f_lower=f_lower, f_ref=f_ref, f_final=f_max)
    # else:
    hp, hc = pw.get_fd_waveform(central_param,
                                delta_f=df,
                                f_lower=f_lower,
                                f_ref=f_ref,
                                f_final=f_max)
    hp0, hc0 = pw.get_fd_waveform(temp_param0,
                                  delta_f=df,
                                  f_lower=f_lower,
                                  f_ref=f_ref,
                                  f_final=f_max)
    hp3, hc3 = pw.get_fd_waveform(temp_param3,
                                  delta_f=df,
                                  f_lower=f_lower,
                                  f_ref=f_ref,
                                  f_final=f_max)

    # FIXME: currently will using aLIGOZeroDetHighPower
    # FIXME: add how to make sure, psd numerical problems of psd
    if psd is not None:
        ipsd = pp.interpolate(psd, df)
    else:
        ipsd = None
        # ipsd = pp.aLIGOZeroDetHighPower(flen, df, f_lower)
        # ipsd = pp.interpolate(ipsd, df)
        # ipsd.data[-1] = 2.0*ipsd.data[-2]
        # ipsd = ipsd.astype(hp.dtype)

    mat0, _ = pf.match(hp, hp0, ipsd, f_lower, f_max)
    mat3, _ = pf.match(hp, hp3, ipsd, f_lower, f_max)
    # print mat0, mat3, miss_match
    #     print central_param['tau0'], central_param['tau3']
    #     print temp_param0['tau0'], temp_param0['tau3']
    #     print temp_param3['tau0'], temp_param3['tau3']
    #     print float(temp_param0['tau0'])-float(central_param['tau0'])
    #     print temp_param3['tau3']-central_param['tau3']
    dtau0_range = miss_match * (temp_param0['tau0'] -
                                central_param['tau0']) / (1.0 - mat0)
    dtau3_range = miss_match * (temp_param3['tau3'] -
                                central_param['tau3']) / (1.0 - mat3)
    #     print dtau0_range, dtau3_range
    return dtau0_range, dtau3_range
Beispiel #12
0
def get_fd_waveform_from_td(**params):
    """ Return time domain version of fourier domain approximant.

    This returns a frequency domain version of a fourier domain approximant,
    with padding and tapering at the start of the waveform.

    Parameters
    ----------
    params: dict
        The parameters defining the waveform to generator.
        See `get_td_waveform`.

    Returns
    -------
    hp: pycbc.types.FrequencySeries
        Plus polarization time series
    hc: pycbc.types.FrequencySeries
        Cross polarization time series
    """

    # determine the duration to use
    full_duration = duration = get_waveform_filter_length_in_time(**params)
    nparams = params.copy()

    while full_duration < duration * 1.5:
        full_duration = get_waveform_filter_length_in_time(**nparams)
        nparams['f_lower'] -= 1

    if 'f_fref' not in nparams:
        nparams['f_ref'] = params['f_lower']

    # We'll try to do the right thing and figure out what the frequency
    # end is. Otherwise, we'll just assume 2048 Hz.
    # (consider removing as we hopefully have better estimates for more
    # approximants
    try:
        f_end = get_waveform_end_frequency(**params)
        delta_t = (0.5 / pnutils.nearest_larger_binary_number(f_end))
    except:
        delta_t = 1.0 / 2048

    nparams['delta_t'] = delta_t
    hp, hc = get_td_waveform(**nparams)

    # Resize to the right duration
    tsamples = int(1.0 / params['delta_f'] / delta_t)

    if tsamples < len(hp):
        raise ValueError("The frequency spacing (df = {}) is too low to "
                         "generate the {} approximant from the time "
                         "domain".format(params['delta_f'], params['approximant']))

    hp.resize(tsamples)
    hc.resize(tsamples)

    # apply the tapering, we will use a safety factor here to allow for
    # somewhat innacurate duration difference estimation.
    window = (full_duration - duration) * 0.8
    hp = wfutils.td_taper(hp, hp.start_time, hp.start_time + window)
    hc = wfutils.td_taper(hc, hc.start_time, hc.start_time + window)

    # avoid wraparound
    hp = hp.to_frequencyseries().cyclic_time_shift(hp.start_time)
    hc = hc.to_frequencyseries().cyclic_time_shift(hc.start_time)
    return hp, hc
Beispiel #13
0
def get_fd_waveform_from_td(**params):
    """ Return time domain version of fourier domain approximant.

    This returns a frequency domain version of a fourier domain approximant,
    with padding and tapering at the start of the waveform.

    Parameters
    ----------
    params: dict
        The parameters defining the waveform to generator.
        See `get_td_waveform`.

    Returns
    -------
    hp: pycbc.types.FrequencySeries
        Plus polarization time series
    hc: pycbc.types.FrequencySeries
        Cross polarization time series
    """

    # determine the duration to use
    full_duration = duration = get_waveform_filter_length_in_time(**params)
    nparams = params.copy()

    while full_duration < duration * 1.5:
        full_duration = get_waveform_filter_length_in_time(**nparams)
        nparams['f_lower'] -= 1

    if 'f_fref' not in nparams:
        nparams['f_ref'] = params['f_lower']

    # We'll try to do the right thing and figure out what the frequency
    # end is. Otherwise, we'll just assume 2048 Hz.
    # (consider removing as we hopefully have better estimates for more
    # approximants
    try:
        f_end = get_waveform_end_frequency(**params)
        delta_t = (0.5 / pnutils.nearest_larger_binary_number(f_end))
    except:
        delta_t = 1.0 / 2048

    nparams['delta_t'] = delta_t
    hp, hc = get_td_waveform(**nparams)

    # Resize to the right duration
    tsamples = int(1.0 / params['delta_f'] / delta_t)

    if tsamples < len(hp):
        raise ValueError("The frequency spacing (df = {}) is too low to "
                         "generate the {} approximant from the time "
                         "domain".format(params['delta_f'], params['approximant']))

    hp.resize(tsamples)
    hc.resize(tsamples)

    # apply the tapering, we will use a safety factor here to allow for
    # somewhat innacurate duration difference estimation.
    window = (full_duration - duration) * 0.8
    hp = wfutils.td_taper(hp, hp.start_time, hp.start_time + window)
    hc = wfutils.td_taper(hc, hc.start_time, hc.start_time + window)

    # avoid wraparound
    hp = hp.to_frequencyseries().cyclic_time_shift(hp.start_time)
    hc = hc.to_frequencyseries().cyclic_time_shift(hc.start_time)
    return hp, hc
Beispiel #14
0
    def __getitem__(self, index):
        approximant = self.approximant(index)
        f_end = self.end_frequency(index)

        # Determine the length of time of the filter, rounded up to
        # nearest power of two
        min_buffer = 1.0 + self.minimum_buffer

        from pycbc.waveform.waveform import props
        buff_size = pycbc.waveform.get_waveform_filter_length_in_time(
            approximant, f_lower=self.f_lower, **props(self.table[index]))
        tlen = nearest_larger_binary_number(
            (buff_size + min_buffer) * self.sample_rate)
        flen = tlen / 2 + 1

        delta_f = self.sample_rate / float(tlen)

        if f_end is None or f_end >= (flen * delta_f):
            f_end = (flen - 1) * delta_f

        logging.info("Generating %s, %ss, %i" %
                     (approximant, 1.0 / delta_f, index))

        # Get the waveform filter
        distance = 1.0 / DYN_RANGE_FAC
        htilde = pycbc.waveform.get_waveform_filter(
            zeros(flen, dtype=numpy.complex64),
            self.table[index],
            approximant=approximant,
            f_lower=self.f_lower,
            f_final=f_end,
            delta_f=delta_f,
            delta_t=1.0 / self.sample_rate,
            distance=distance,
            **self.extra_args)

        # If available, record the total duration (which may
        # include ringdown) and the duration up to merger since they will be
        # erased by the type conversion below.
        # NOTE: If these durations are not available the values in self.table
        #       will continue to take the values in the input file.
        if hasattr(htilde, 'length_in_time'):
            if htilde.length_in_time is not None:
                self.table[index].ttotal = htilde.length_in_time
        if hasattr(htilde, 'chirp_length'):
            if htilde.chirp_length is not None:
                self.table[index].template_duration = htilde.chirp_length

        htilde = htilde.astype(numpy.complex64)
        htilde.f_lower = self.f_lower
        htilde.end_frequency = f_end
        htilde.end_idx = int(htilde.end_frequency / htilde.delta_f)
        htilde.params = self.table[index]
        htilde.approximant = approximant
        htilde.chirp_length = htilde.params.template_duration
        htilde.length_in_time = htilde.params.ttotal

        # Add sigmasq as a method of this instance
        htilde.sigmasq = types.MethodType(sigma_cached, htilde)
        htilde._sigmasq = {}

        return htilde