예제 #1
0
    def test_sg(self):
        ### use a sin-gaussian as a signal

        sigt = TimeSeries(self.sig2, self.del_t)
        sig_tilde = make_frequency_series(sigt)

        del_f = sig_tilde.get_delta_f()
        psd = FrequencySeries(self.Psd, del_f)
        flow = self.low_frequency_cutoff

        with _context:
            hautocor, hacorfr, hnrm = matched_filter_core(self.htilde, self.htilde, psd=psd, \
   low_frequency_cutoff=flow, high_frequency_cutoff=self.fmax)
            hautocor = hautocor * float(np.real(1. / hautocor[0]))


            snr, cor, nrm = matched_filter_core(self.htilde, sig_tilde, psd=psd, \
   low_frequency_cutoff=flow, high_frequency_cutoff=self.fmax)

        hacor = Array(hautocor.real(), copy=True)

        indx = np.array([301440, 301450, 301460])

        snr = snr * nrm

        with _context:
            dof, achisq, indices= \
                autochisq_from_precomputed(snr, snr, hacor, indx, stride=3,
                                           num_points=20)

        obt_snr = abs(snr[indices[1]])
        obt_ach = achisq[1]
        self.assertTrue(obt_snr > 12.0 and obt_snr < 15.0)
        self.assertTrue(obt_ach > 6.8e3)
        self.assertTrue(achisq[0] > 6.8e3)
        self.assertTrue(achisq[2] > 6.8e3)
예제 #2
0
파일: estimate.py 프로젝트: mcoughlin/pycbc
def interpolate(series, delta_f):
    """Return a new PSD that has been interpolated to the desired delta_f.

    Parameters
    ----------
    series : FrequencySeries
        Frequency series to be interpolated.
    delta_f : float
        The desired delta_f of the output

    Returns
    -------
    interpolated series : FrequencySeries
        A new FrequencySeries that has been interpolated.
    """
    new_n = (len(series) - 1) * series.delta_f / delta_f + 1
    samples = numpy.arange(0, numpy.rint(new_n)) * delta_f
    interpolated_series = numpy.interp(samples,
                                       series.sample_frequencies.numpy(),
                                       series.numpy())
    return FrequencySeries(interpolated_series,
                           epoch=series.epoch,
                           delta_f=delta_f,
                           dtype=series.dtype)
예제 #3
0
def inverse_spectrum_truncation(psd, max_filter_len, low_frequency_cutoff=None, trunc_method=None):
    """Modify a PSD such that the impulse response associated with its inverse
    square root is no longer than `max_filter_len` time samples. In practice
    this corresponds to a coarse graining or smoothing of the PSD.

    Parameters
    ----------
    psd : FrequencySeries
        PSD whose inverse spectrum is to be truncated.
    max_filter_len : int
        Maximum length of the time-domain filter in samples.
    low_frequency_cutoff : {None, int}
        Frequencies below `low_frequency_cutoff` are zeroed in the output.
    trunc_method : {None, 'hann'}
        Function used for truncating the time-domain filter.
        None produces a hard truncation at `max_filter_len`.

    Returns
    -------
    psd : FrequencySeries
        PSD whose inverse spectrum has been truncated.

    Raises
    ------
    ValueError
        For invalid types or values of `max_filter_len` and `low_frequency_cutoff`.

    Notes
    -----
    See arXiv:gr-qc/0509116 for details.
    """
    # sanity checks
    if type(max_filter_len) is not int or max_filter_len <= 0:
        raise ValueError('max_filter_len must be a positive integer')
    if low_frequency_cutoff is not None and low_frequency_cutoff < 0 \
        or low_frequency_cutoff > psd.sample_frequencies[-1]:
        raise ValueError('low_frequency_cutoff must be within the bandwidth of the PSD')

    N = (len(psd)-1)*2

    inv_asd = FrequencySeries((1. / psd)**0.5, delta_f=psd.delta_f, \
        dtype=complex_same_precision_as(psd))
        
    inv_asd[0] = 0
    inv_asd[N/2] = 0
    q = TimeSeries(numpy.zeros(N), delta_t=(N / psd.delta_f), \
        dtype=real_same_precision_as(psd))

    if low_frequency_cutoff:
        kmin = int(low_frequency_cutoff / psd.delta_f)
        inv_asd[0:kmin] = 0

    ifft(inv_asd, q)
    
    trunc_start = max_filter_len / 2
    trunc_end = N - max_filter_len / 2

    if trunc_method == 'hann':
        trunc_window = Array(numpy.hanning(max_filter_len), dtype=q.dtype)
        q[0:trunc_start] *= trunc_window[max_filter_len/2:max_filter_len]
        q[trunc_end:N] *= trunc_window[0:max_filter_len/2]

    q[trunc_start:trunc_end] = 0
    psd_trunc = FrequencySeries(numpy.zeros(len(psd)), delta_f=psd.delta_f, \
                                dtype=complex_same_precision_as(psd))
    fft(q, psd_trunc)
    psd_trunc *= psd_trunc.conj()
    psd_out = 1. / abs(psd_trunc)

    return psd_out
예제 #4
0
def logv_lookup(vmax, delta):
    vec = numpy.arange(0, vmax * 1.2, delta)
    vec[1:len(vec)] = numpy.log(vec[1:len(vec)])
    return FrequencySeries(vec, delta_f=delta).astype(float32)
예제 #5
0
파일: ringdown.py 프로젝트: molodiuc/pycbc
def get_fd_lm_allmodes(template=None, **kwargs):
    """Return frequency domain ringdown with all the modes specified.

    Parameters
    ----------
    template: object
        An object that has attached properties. This can be used to substitute
        for keyword arguments. A common example would be a row in an xml table.
    final_mass : float
        Mass of the final black hole.
    final_spin : float
        Spin of the final black hole.
    lmns : list
        Desired lmn modes as strings (lm modes available: 22, 21, 33, 44, 55).
        The n specifies the number of overtones desired for the corresponding
        lm pair (maximum n=8).
        Example: lmns = ['223','331'] are the modes 220, 221, 222, and 330
    amp220 : float
        Amplitude of the fundamental 220 mode.
    amplmn : float
        Fraction of the amplitude of the lmn overtone relative to the 
        fundamental mode, as many as the number of subdominant modes.
    philmn : float
        Phase of the lmn overtone, as many as the number of modes.
    delta_f : {None, float}, optional
        The frequency step used to generate the ringdown.
        If None, it will be set to the inverse of the time at which the
        amplitude is 1/1000 of the peak amplitude (the minimum of all modes).
    f_lower: {None, float}, optional
        The starting frequency of the output frequency series.
        If None, it will be set to delta_f.
    f_final : {None, float}, optional
        The ending frequency of the output frequency series.
        If None, it will be set to the frequency at which the amplitude
        is 1/1000 of the peak amplitude (the maximum of all modes).

    Returns
    -------
    hplustilde: FrequencySeries
        The plus phase of a ringdown with the lm modes specified and
        n overtones in frequency domain.
    hcrosstilde: FrequencySeries
        The cross phase of a ringdown with the lm modes specified and
        n overtones in frequency domain.
    """

    input_params = props(template, lm_allmodes_required_args, **kwargs)

    # Get required args
    final_mass = input_params['final_mass']
    final_spin = input_params['final_spin']
    lmns = input_params['lmns']
    for lmn in lmns:
        if int(lmn[2]) == 0:
            raise ValueError('Number of overtones (nmodes) must be greater '
                             'than zero.')
    # The following may not be in input_params
    delta_f = input_params.pop('delta_f', None)
    f_lower = input_params.pop('f_lower', None)
    f_final = input_params.pop('f_final', None)

    if delta_f is None:
        delta_f = lm_deltaf(final_mass, final_spin, lmns)
    if f_final is None:
        f_final = lm_ffinal(final_mass, final_spin, lmns)
    if f_lower is None:
        f_lower = delta_f
    kmax = int(f_final / delta_f) + 1

    outplustilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                   delta_f=delta_f)
    outcrosstilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                    delta_f=delta_f)
    for lmn in lmns:
        l, m, nmodes = int(lmn[0]), int(lmn[1]), int(lmn[2])
        hplustilde, hcrosstilde = get_fd_lm(l=l,
                                            m=m,
                                            nmodes=nmodes,
                                            delta_f=delta_f,
                                            f_lower=f_lower,
                                            f_final=f_final,
                                            **input_params)
        outplustilde.data += hplustilde.data
        outcrosstilde.data += hcrosstilde.data

    return outplustilde, outcrosstilde
예제 #6
0
파일: ringdown.py 프로젝트: molodiuc/pycbc
def get_fd_qnm(template=None, **kwargs):
    """Return a frequency domain damped sinusoid.

    Parameters
    ----------
    template: object
        An object that has attached properties. This can be used to substitute
        for keyword arguments. A common example would be a row in an xml table.
    f_0 : float
        The ringdown-frequency.
    tau : float
        The damping time of the sinusoid.
    phi : float
        The initial phase of the ringdown.
    amp : float
        The amplitude of the ringdown (constant for now).
    t_0 :  {0, float}, optional
        The starting time of the ringdown.
    delta_f : {None, float}, optional
        The frequency step used to generate the ringdown.
        If None, it will be set to the inverse of the time at which the
        amplitude is 1/1000 of the peak amplitude.
    f_lower: {None, float}, optional
        The starting frequency of the output frequency series.
        If None, it will be set to delta_f.
    f_final : {None, float}, optional
        The ending frequency of the output frequency series.
        If None, it will be set to the frequency at which the amplitude is 
        1/1000 of the peak amplitude.

    Returns
    -------
    hplustilde: FrequencySeries
        The plus phase of the ringdown in frequency domain.
    hcrosstilde: FrequencySeries
        The cross phase of the ringdown in frequency domain.
    """

    input_params = props(template, qnm_required_args, **kwargs)

    f_0 = input_params.pop('f_0')
    tau = input_params.pop('tau')
    amp = input_params.pop('amp')
    phi = input_params.pop('phi')
    # the following have defaults, and so will be populated
    t_0 = input_params.pop('t_0')
    # the following may not be in input_params
    delta_f = input_params.pop('delta_f', None)
    f_lower = input_params.pop('f_lower', None)
    f_final = input_params.pop('f_final', None)

    if delta_f is None:
        delta_f = 1. / qnm_time_decay(tau, 1. / 1000)
    if f_lower is None:
        f_lower = delta_f
        kmin = 0
    else:
        kmin = int(f_lower / delta_f)
    if f_final is None:
        f_final = qnm_freq_decay(f_0, tau, 1. / 1000)
    if f_final > max_freq:
        f_final = max_freq
    kmax = int(f_final / delta_f) + 1

    freqs = numpy.arange(kmin, kmax) * delta_f

    denominator = 1 + (4j * pi * freqs *
                       tau) - (4 * pi_sq *
                               (freqs * freqs - f_0 * f_0) * tau * tau)
    norm = amp * tau / denominator
    if t_0 != 0:
        time_shift = numpy.exp(-1j * two_pi * freqs * t_0)
        norm *= time_shift

    # Analytical expression for the Fourier transform of the ringdown (damped sinusoid)
    hp_tilde = norm * ((1 + 2j * pi * freqs * tau) * numpy.cos(phi) -
                       two_pi * f_0 * tau * numpy.sin(phi))
    hc_tilde = norm * ((1 + 2j * pi * freqs * tau) * numpy.sin(phi) +
                       two_pi * f_0 * tau * numpy.cos(phi))

    hplustilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                 delta_f=delta_f)
    hcrosstilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                  delta_f=delta_f)
    hplustilde.data[kmin:kmax] = hp_tilde
    hcrosstilde.data[kmin:kmax] = hc_tilde

    return hplustilde, hcrosstilde
예제 #7
0
def calc_psd_variation(strain, psd_short_segment, psd_long_segment, overlap,
                       low_freq, high_freq):
    """Calculates time series of PSD variability

    This function first splits the segment up in to 512 second chunks. It
    then calculates the PSD over this 512 second period as well as in 4
    second chunks throughout each 512 second period. Next the function
    estimates how different the 4 second PSD is to the 512 second PSD and
    produces a timeseries of this variability.

    Parameters
    ----------
    strain : TimeSeries
        Input strain time series to estimate PSDs
    psd_short_segment : {float, 4}
        Duration of the short segments for PSD estimation in seconds.
    psd_long_segment : {float, 512}
        Duration of the long segments for PSD estimation in seconds.
    overlap : {float, 0.5}
        Duration in seconds to use for each sample of the PSD.
    low_freq : {float, 20}
        Minimum frequency to consider the comparison between PSDs.
    high_freq : {float, 512}
        Maximum frequency to consider the comparison between PSDs.

    Returns
    -------
    psd_var : TimeSeries
        Time series of the variability in the PSD estimation
    """

    # Calculate strain precision
    if strain.precision == 'single':
        fs_dtype = numpy.float32
    elif strain.precision == 'double':
        fs_dtype = numpy.float64

    # Convert start and end times immediately to floats
    start_time = numpy.float(strain.start_time)
    end_time = numpy.float(strain.end_time)

    # Find the times of the long segments
    times_long = numpy.arange(start_time, end_time, psd_long_segment)

    # Set up the empty time series for the PSD variation estimate
    psd_var = TimeSeries(zeros(
        int(numpy.ceil((end_time - start_time) / psd_short_segment))),
                         delta_t=psd_short_segment,
                         copy=False,
                         epoch=start_time)

    ind = 0
    for tlong in times_long:
        # Calculate PSD for long segment and separate the long segment in to
        # overlapping shorter segments
        if tlong + psd_long_segment <= end_time:
            psd_long = strain.time_slice(tlong,
                                         tlong + psd_long_segment).psd(overlap)
            times_short = numpy.arange(tlong, tlong + psd_long_segment,
                                       psd_short_segment)
        else:
            psd_long = strain.time_slice(end_time - psd_long_segment,
                                         end_time).psd(overlap)
            times_short = numpy.arange(tlong, end_time, psd_short_segment)
        # Calculate the PSD of the shorter segments
        psd_short = []
        for tshort in times_short:
            if tshort + psd_short_segment * 2 <= end_time:
                pshort = strain.time_slice(tshort, tshort +
                                           psd_short_segment * 2).psd(overlap)
            else:
                pshort = strain.time_slice(tshort - psd_short_segment,
                                           end_time).psd(overlap)
            psd_short.append(pshort)
        # Estimate the range of the PSD to compare
        kmin = int(low_freq / psd_long.delta_f)
        kmax = int(high_freq / psd_long.delta_f)
        # Comapre the PSD of the short segment to the long segment
        # The weight factor gives the rough response of a cbc template across
        # the defined frequency range given the expected PSD (i.e. long PSD)
        # Then integrate the weighted ratio of the actual PSD (i.e. short PSD)
        # with the expected PSD (i.e. long PSD) over the specified frequency
        # range
        freqs = FrequencySeries(psd_long.sample_frequencies,
                                delta_f=psd_long.delta_f,
                                epoch=psd_long.epoch,
                                dtype=fs_dtype)
        weight = numpy.array(freqs[kmin:kmax]**(-7. / 3.) /
                             psd_long[kmin:kmax])
        weight /= weight.sum()
        diff = numpy.array([
            (weight *
             numpy.array(p_short[kmin:kmax] / psd_long[kmin:kmax])).sum()
            for p_short in psd_short
        ])

        # Store variation value
        for i, val in enumerate(diff):
            psd_var[ind + i] = val

        ind = ind + len(diff)

    return psd_var
예제 #8
0
    def adjust_strain(self, strain, delta_fs=None, delta_qinv=None,
                      delta_fc=None, kappa_c=1.0, kappa_tst_re=1.0,
                      kappa_tst_im=0.0, kappa_pu_re=1.0, kappa_pu_im=0.0):
        """Adjust the FrequencySeries strain by changing the time-dependent
        calibration parameters kappa_c(t), kappa_a(t), f_c(t), fs, and qinv.

        Parameters
        ----------
        strain : FrequencySeries
            The strain data to be adjusted.
        delta_fc : float
            Change in coupled-cavity (CC) pole at time t.
        kappa_c : float
            Scalar correction factor for sensing function c0 at time t.
        kappa_tst_re : float
            Real part of scalar correction factor for actuation function
            A_{tst0} at time t.
        kappa_tst_im : float
            Imaginary part of scalar correction factor for actuation function
            A_tst0 at time t.
        kappa_pu_re : float
            Real part of scalar correction factor for actuation function
            A_{pu0} at time t.
        kappa_pu_im : float
            Imaginary part of scalar correction factor for actuation function
            A_{pu0} at time t.
        fs : float
            Spring frequency for signal recycling cavity.
        qinv : float
            Inverse quality factor for signal recycling cavity.

        Returns
        -------
        strain_adjusted : FrequencySeries
            The adjusted strain.
        """
        fc = self.fc0 + delta_fc if delta_fc else self.fc0
        fs = self.fs0 + delta_fs if delta_fs else self.fs0
        qinv = self.qinv0 + delta_qinv if delta_qinv else self.qinv0

        # calculate adjusted response function
        r_adjusted = self.update_r(fs=fs, qinv=qinv, fc=fc, kappa_c=kappa_c,
                                   kappa_tst_re=kappa_tst_re,
                                   kappa_tst_im=kappa_tst_im,
                                   kappa_pu_re=kappa_pu_re,
                                   kappa_pu_im=kappa_pu_im)

        # calculate error function
        k = r_adjusted / self.r0

        # decompose into amplitude and unwrapped phase
        k_amp = np.abs(k)
        k_phase = np.unwrap(np.angle(k))

        # convert to FrequencySeries by interpolating then resampling
        order = 1
        k_amp_off = UnivariateSpline(self.freq, k_amp, k=order, s=0)
        k_phase_off = UnivariateSpline(self.freq, k_phase, k=order, s=0)
        freq_even = strain.sample_frequencies.numpy()
        k_even_sample = k_amp_off(freq_even) * \
                        np.exp(1.0j * k_phase_off(freq_even))
        strain_adjusted = FrequencySeries(strain.numpy() * \
                                          k_even_sample,
                                          delta_f=strain.delta_f)

        return strain_adjusted
예제 #9
0
def taylorf2(**kwds):
    """ Return a TaylorF2 waveform using CUDA to generate the phase and amplitude
    """
    # Pull out the input arguments
    delta_f = kwds['delta_f']
    distance = kwds['distance']
    mass1 = kwds['mass1']
    mass2 = kwds['mass2']
    phase_order = int(kwds['phase_order'])
    amplitude_order = int(kwds['amplitude_order'])
    phi0 = kwds['phi0']

    tC = -1.0 / delta_f

    #Calculate the spin corrections
    beta, sigma, gamma = pycbc.pnutils.mass1_mass2_spin1z_spin2z_to_beta_sigma_gamma(
        mass1, mass2, kwds['spin1z'], kwds['spin2z'])

    #Calculate teh PN terms #TODO: replace with functions in lalsimulation!###
    M = float(mass1) + float(mass2)
    eta = mass1 * mass2 / (M * M)
    theta = -11831. / 9240.
    lambdaa = -1987. / 3080.0
    pfaN = 3.0 / (128.0 * eta)
    pfa2 = 5 * (743.0 / 84 + 11.0 * eta) / 9.0
    pfa3 = -16.0 * lal.PI + 4.0 * beta
    pfa4 = 5.0*(3058.673/7.056 + 5429.0/7.0 * eta + 617.0 * eta*eta)/72.0 - \
            10.0*sigma
    pfa5 = 5.0 / 9.0 * (7729.0 / 84.0 - 13.0 * eta) * lal.PI - gamma
    pfl5 = 5.0 / 3.0 * (7729.0 / 84.0 - 13.0 * eta) * lal.PI - gamma * 3
    pfa6 = (11583.231236531/4.694215680 - 640.0/3.0 * lal.PI * lal.PI- \
            6848.0/21.0*lal.GAMMA) + \
            eta * (-15335.597827/3.048192 + 2255./12. * lal.PI * \
            lal.PI - 1760./3.*theta +12320./9.*lambdaa) + \
            eta*eta * 76055.0/1728.0 - \
            eta*eta*eta*  127825.0/1296.0
    pfl6 = -6848.0 / 21.0
    pfa7 = lal.PI * 5.0/756.0 * ( 15419335.0/336.0 + 75703.0/2.0 * eta - \
            14809.0 * eta*eta)

    FTaN = 32.0 * eta * eta / 5.0
    FTa2 = -(12.47 / 3.36 + 3.5 / 1.2 * eta)
    FTa3 = 4.0 * lal.PI
    FTa4 = -(44.711 / 9.072 - 92.71 / 5.04 * eta - 6.5 / 1.8 * eta * eta)
    FTa5 = -(81.91 / 6.72 + 58.3 / 2.4 * eta) * lal.PI
    FTa6 = (664.3739519 / 6.9854400 + 16.0 / 3.0 * lal.PI * lal.PI -
            17.12 / 1.05 * lal.GAMMA +
            (4.1 / 4.8 * lal.PI * lal.PI - 134.543 / 7.776) * eta -
            94.403 / 3.024 * eta * eta - 7.75 / 3.24 * eta * eta * eta)
    FTl6 = -8.56 / 1.05
    FTa7 = -(162.85/5.04 - 214.745/1.728 * eta - 193.385/3.024 * eta*eta) \
            * lal.PI

    dETaN = 2 * -eta / 2.0
    dETa1 = 2 * -(3.0 / 4.0 + 1.0 / 12.0 * eta)
    dETa2 = 3 * -(27.0 / 8.0 - 19.0 / 8.0 * eta + 1. / 24.0 * eta * eta)
    dETa3 = 4 * -(67.5 / 6.4 -
                  (344.45 / 5.76 - 20.5 / 9.6 * lal.PI * lal.PI) * eta +
                  15.5 / 9.6 * eta * eta + 3.5 / 518.4 * eta * eta * eta)

    amp0 = -4. * mass1 * mass2 / (1.0e+06 * float(distance) * lal.PC_SI )* \
                    lal.MRSUN_SI * lal.MTSUN_SI * sqrt(lal.PI/12.0)

    m_sec = M * lal.MTSUN_SI
    piM = lal.PI * m_sec

    kmin = int(kwds['f_lower'] / float(delta_f))

    vISCO = 1. / sqrt(6.)
    fISCO = vISCO * vISCO * vISCO / piM
    kmax = int(fISCO / delta_f)
    f_max = fISCO
    n = int(f_max / delta_f) + 1

    htilde = FrequencySeries(zeros(n, dtype=numpy.complex128),
                             delta_f=delta_f,
                             copy=False)
    taylorf2_kernel(htilde.data[kmin:kmax], kmin, phase_order, amplitude_order,
                    delta_f, piM, pfaN, pfa2, pfa3, pfa4, pfa5, pfl5, pfa6,
                    pfl6, pfa7, FTaN, FTa2, FTa3, FTa4, FTa5, FTa6, FTl6, FTa7,
                    dETaN, dETa1, dETa2, dETa3, amp0, tC, phi0)

    hp = htilde
    hc = htilde * 1j
    return hp, hc
예제 #10
0
def get_fd_lm(template=None, **kwargs):
    """Return frequency domain lm mode with a given number of overtones.

    Parameters
    ----------
    template: object
        An object that has attached properties. This can be used to substitute
        for keyword arguments. A common example would be a row in an xml table.
    freqs : dict
        {lmn:f_lmn} Dictionary of the central frequencies for each overtone,
        as many as number of modes.
    taus : dict
        {lmn:tau_lmn} Dictionary of the damping times for each overtone,
        as many as number of modes.
    l : int
        l mode (lm modes available: 22, 21, 33, 44, 55).
    m : int
        m mode (lm modes available: 22, 21, 33, 44, 55).
    nmodes: int
        Number of overtones desired (maximum n=8)
    amplmn : float
        Amplitude of the lmn overtone, as many as the number of nmodes.
    philmn : float
        Phase of the lmn overtone, as many as the number of modes. Should also
        include the information from the azimuthal angle (phi + m*Phi).
    inclination : {0., float}, optional
        Inclination of the system in radians. Default is 0 (face on).
    delta_f : {None, float}, optional
        The frequency step used to generate the ringdown.
        If None, it will be set to the inverse of the time at which the
        amplitude is 1/1000 of the peak amplitude (the minimum of all modes).
    f_lower: {None, float}, optional
        The starting frequency of the output frequency series.
        If None, it will be set to delta_f.
    f_final : {None, float}, optional
        The ending frequency of the output frequency series.
        If None, it will be set to the frequency at which the amplitude
        is 1/1000 of the peak amplitude (the maximum of all modes).

    Returns
    -------
    hplustilde: FrequencySeries
        The plus phase of a lm mode with n overtones in frequency domain.
    hcrosstilde: FrequencySeries
        The cross phase of a lm mode with n overtones in frequency domain.
    """

    input_params = props(template, lm_required_args, **kwargs)

    # Get required args
    amps, phis = lm_amps_phases(**input_params)
    f_0 = input_params.pop('freqs')
    tau = input_params.pop('taus')
    l, m = input_params.pop('l'), input_params.pop('m')
    inc = input_params.pop('inclination', 0.)
    nmodes = input_params.pop('nmodes')
    if int(nmodes) == 0:
        raise ValueError('Number of overtones (nmodes) must be greater '
                         'than zero.')
    # The following may not be in input_params
    delta_f = input_params.pop('delta_f', None)
    f_lower = input_params.pop('f_lower', None)
    f_final = input_params.pop('f_final', None)

    if delta_f is None:
        delta_f = lm_deltaf(tau, ['%d%d%d' %(l,m,nmodes)])
    if f_final is None:
        f_final = lm_ffinal(f_0, tau, ['%d%d%d' %(l, m, nmodes)])
    kmax = int(f_final / delta_f) + 1

    outplus = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f)
    outcross = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f)

    for n in range(nmodes):
        hplus, hcross = get_fd_qnm(template=None, f_0=f_0['%d%d%d' %(l,m,n)],
                            tau=tau['%d%d%d' %(l,m,n)], 
                            amp=amps['%d%d%d' %(l,m,n)],
                            phi=phis['%d%d%d' %(l,m,n)],
                            inclination=inc, l=l, m=m, delta_f=delta_f,
                            f_lower=f_lower, f_final=f_final)
        outplus.data += hplus.data
        outcross.data += hcross.data

    return outplus, outcross
예제 #11
0
def calculate_acf(data, delta_t=1.0, unbiased=False):
    r"""Calculates the one-sided autocorrelation function.

    Calculates the autocorrelation function (ACF) and returns the one-sided
    ACF. The ACF is defined as the autocovariance divided by the variance. The
    ACF can be estimated using

    .. math::

        \hat{R}(k) = \frac{1}{n \sigma^{2}} \sum_{t=1}^{n-k} \left( X_{t} - \mu \right) \left( X_{t+k} - \mu \right) 

    Where :math:`\hat{R}(k)` is the ACF, :math:`X_{t}` is the data series at
    time t, :math:`\mu` is the mean of :math:`X_{t}`, and :math:`\sigma^{2}` is
    the variance of :math:`X_{t}`.

    Parameters
    -----------
    data : TimeSeries or numpy.array
        A TimeSeries or numpy.array of data.
    delta_t : float
        The time step of the data series if it is not a TimeSeries instance.
    unbiased : bool
        If True the normalization of the autocovariance function is n-k
        instead of n. This is called the unbiased estimation of the
        autocovariance. Note that this does not mean the ACF is unbiased.

    Returns
    -------
    acf : numpy.array
        If data is a TimeSeries then acf will be a TimeSeries of the
        one-sided ACF. Else acf is a numpy.array.
    """

    # if given a TimeSeries instance then get numpy.array
    if isinstance(data, TimeSeries):
        y = data.numpy()
        delta_t = data.delta_t
    else:
        y = data

    # Zero mean
    y = y - y.mean()
    ny_orig = len(y)

    npad = 1
    while npad < 2*ny_orig:
        npad = npad << 1
    ypad = numpy.zeros(npad)
    ypad[:ny_orig] = y    
        
    # FFT data minus the mean
    fdata = TimeSeries(ypad, delta_t=delta_t).to_frequencyseries()

    # correlate
    # do not need to give the congjugate since correlate function does it
    cdata = FrequencySeries(zeros(len(fdata), dtype=numpy.complex64),
                           delta_f=fdata.delta_f, copy=False)
    correlate(fdata, fdata, cdata)

    # IFFT correlated data to get unnormalized autocovariance time series
    acf = cdata.to_timeseries()
    acf = acf[:ny_orig]

    # normalize the autocovariance
    # note that dividing by acf[0] is the same as ( y.var() * len(acf) )
    if unbiased:
        acf /= ( y.var() * numpy.arange(len(acf), 0, -1) )
    else:
        acf /= acf[0]

    # return input datatype
    if isinstance(data, TimeSeries):
        return TimeSeries(acf, delta_t=delta_t)
    else:
        return acf
예제 #12
0
def get_fd_from_final_mass_spin(template=None, distance=None, **kwargs):
    """Return frequency domain ringdown with all the modes specified.

    Parameters
    ----------
    template: object
        An object that has attached properties. This can be used to substitute
        for keyword arguments. A common example would be a row in an xml table.
    distance : {None, float}, optional
        Luminosity distance of the system. If specified, the returned ringdown
        will contain the factor (final_mass/distance).
    final_mass : float
        Mass of the final black hole.
    final_spin : float
        Spin of the final black hole.
    lmns : list
        Desired lmn modes as strings (lm modes available: 22, 21, 33, 44, 55).
        The n specifies the number of overtones desired for the corresponding
        lm pair (maximum n=8).
        Example: lmns = ['223','331'] are the modes 220, 221, 222, and 330
    amp220 : float
        Amplitude of the fundamental 220 mode. Note that if distance is given,
        this parameter will have a completely different order of magnitude.
        See table II in https://arxiv.org/abs/1107.0854 for an estimate.
    amplmn : float
        Fraction of the amplitude of the lmn overtone relative to the
        fundamental mode, as many as the number of subdominant modes.
    philmn : float
        Phase of the lmn overtone, as many as the number of modes. Should also
        include the information from the azimuthal angle (phi + m*Phi).
    inclination : float
        Inclination of the system in radians.
    delta_f : {None, float}, optional
        The frequency step used to generate the ringdown.
        If None, it will be set to the inverse of the time at which the
        amplitude is 1/1000 of the peak amplitude (the minimum of all modes).
    f_lower: {None, float}, optional
        The starting frequency of the output frequency series.
        If None, it will be set to delta_f.
    f_final : {None, float}, optional
        The ending frequency of the output frequency series.
        If None, it will be set to the frequency at which the amplitude
        is 1/1000 of the peak amplitude (the maximum of all modes).

    Returns
    -------
    hplustilde: FrequencySeries
        The plus phase of a ringdown with the lm modes specified and
        n overtones in frequency domain.
    hcrosstilde: FrequencySeries
        The cross phase of a ringdown with the lm modes specified and
        n overtones in frequency domain.
    """

    input_params = props(template, mass_spin_required_args, **kwargs)

    # Get required args
    final_mass = input_params['final_mass']
    final_spin = input_params['final_spin']
    lmns = input_params['lmns']
    for lmn in lmns:
        if int(lmn[2]) == 0:
            raise ValueError('Number of overtones (nmodes) must be greater '
                             'than zero.')
    # The following may not be in input_params
    delta_f = input_params.pop('delta_f', None)
    f_lower = input_params.pop('f_lower', None)
    f_final = input_params.pop('f_final', None)

    f_0, tau = get_lm_f0tau_allmodes(final_mass, final_spin, lmns)

    if not delta_f:
        delta_f = lm_deltaf(tau, lmns)
    if not f_final:
        f_final = lm_ffinal(f_0, tau, lmns)
    if not f_lower:
        f_lower = delta_f
    kmax = int(f_final / delta_f) + 1

    outplustilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                   delta_f=delta_f)
    outcrosstilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                    delta_f=delta_f)
    for lmn in lmns:
        l, m, nmodes = int(lmn[0]), int(lmn[1]), int(lmn[2])
        hplustilde, hcrosstilde = get_fd_lm(freqs=f_0,
                                            taus=tau,
                                            l=l,
                                            m=m,
                                            nmodes=nmodes,
                                            delta_f=delta_f,
                                            f_lower=f_lower,
                                            f_final=f_final,
                                            **input_params)
        outplustilde.data += hplustilde.data
        outcrosstilde.data += hcrosstilde.data

    norm = Kerr_factor(final_mass, distance) if distance else 1.
    return norm * outplustilde, norm * outcrosstilde
예제 #13
0
def get_fd_from_freqtau(template=None, **kwargs):
    """Return frequency domain ringdown with all the modes specified.

    Parameters
    ----------
    template: object
        An object that has attached properties. This can be used to substitute
        for keyword arguments. A common example would be a row in an xml table.
    lmns : list
        Desired lmn modes as strings (lm modes available: 22, 21, 33, 44, 55).
        The n specifies the number of overtones desired for the corresponding
        lm pair (maximum n=8).
        Example: lmns = ['223','331'] are the modes 220, 221, 222, and 330
    f_lmn: float
        Central frequency of the lmn overtone, as many as number of modes.
    tau_lmn: float
        Damping time of the lmn overtone, as many as number of modes.
    amp220 : float
        Amplitude of the fundamental 220 mode.
    amplmn : float
        Fraction of the amplitude of the lmn overtone relative to the
        fundamental mode, as many as the number of subdominant modes.
    philmn : float
        Phase of the lmn overtone, as many as the number of modes. Should also
        include the information from the azimuthal angle (phi + m*Phi).
    inclination : {None, float}, optional
        Inclination of the system in radians. If None, the spherical harmonics
        will be set to 1.
    delta_f : {None, float}, optional
        The frequency step used to generate the ringdown.
        If None, it will be set to the inverse of the time at which the
        amplitude is 1/1000 of the peak amplitude (the minimum of all modes).
    f_lower: {None, float}, optional
        The starting frequency of the output frequency series.
        If None, it will be set to delta_f.
    f_final : {None, float}, optional
        The ending frequency of the output frequency series.
        If None, it will be set to the frequency at which the amplitude
        is 1/1000 of the peak amplitude (the maximum of all modes).

    Returns
    -------
    hplustilde: FrequencySeries
        The plus phase of a ringdown with the lm modes specified and
        n overtones in frequency domain.
    hcrosstilde: FrequencySeries
        The cross phase of a ringdown with the lm modes specified and
        n overtones in frequency domain.
    """

    input_params = props(template, freqtau_required_args, **kwargs)

    # Get required args
    f_0, tau = lm_freqs_taus(**input_params)
    lmns = input_params['lmns']
    for lmn in lmns:
        if int(lmn[2]) == 0:
            raise ValueError('Number of overtones (nmodes) must be greater '
                             'than zero.')
    # The following may not be in input_params
    inc = input_params.pop('inclination', None)
    delta_f = input_params.pop('delta_f', None)
    f_lower = input_params.pop('f_lower', None)
    f_final = input_params.pop('f_final', None)

    if not delta_f:
        delta_f = lm_deltaf(tau, lmns)
    if not f_final:
        f_final = lm_ffinal(f_0, tau, lmns)
    if not f_lower:
        f_lower = delta_f
    kmax = int(f_final / delta_f) + 1

    outplustilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                   delta_f=delta_f)
    outcrosstilde = FrequencySeries(zeros(kmax, dtype=complex128),
                                    delta_f=delta_f)
    for lmn in lmns:
        l, m, nmodes = int(lmn[0]), int(lmn[1]), int(lmn[2])
        hplustilde, hcrosstilde = get_fd_lm(freqs=f_0,
                                            taus=tau,
                                            l=l,
                                            m=m,
                                            nmodes=nmodes,
                                            inclination=inc,
                                            delta_f=delta_f,
                                            f_lower=f_lower,
                                            f_final=f_final,
                                            **input_params)
        outplustilde.data += hplustilde.data
        outcrosstilde.data += hcrosstilde.data

    return outplustilde, outcrosstilde
예제 #14
0
def colored_noise(psd, start_time, end_time, seed=0, low_frequency_cutoff=1.0):
    """ Create noise from a PSD

    Return noise from the chosen PSD. Note that if unique noise is desired
    a unique seed should be provided.

    Parameters
    ----------
    psd : pycbc.types.FrequencySeries
        PSD to color the noise
    start_time : int
        Start time in GPS seconds to generate noise
    end_time : int
        End time in GPS seconds to generate nosie
    seed : {None, int}
        The seed to generate the noise.
    low_frequency_cutof : {10.0, float}
        The low frequency cutoff to pass to the PSD generation.

    Returns
    --------
    noise : TimeSeries
        A TimeSeries containing gaussian noise colored by the given psd.
    """
    psd = psd * 1
    flen = int(SAMPLE_RATE / psd.delta_f) / 2 + 1
    oldlen = len(psd)
    psd.resize(flen)
    # Want to avoid zeroes in PSD.
    max_val = psd.max()
    for i in xrange(len(psd)):
        if i >= (oldlen - 1):
            psd.data[i] = psd[oldlen - 2]
        if psd[i] == 0:
            psd.data[i] = max_val
    wn_dur = int(end_time - start_time) + 2 * FILTER_LENGTH
    if psd.delta_f >= 1. / (2. * FILTER_LENGTH):
        # If the PSD is short enough, this method is less memory intensive than
        # resizing and then calling inverse_spectrum_truncation
        psd = pycbc.psd.interpolate(psd, 1.0 / (2. * FILTER_LENGTH))
        # inverse_spectrum_truncation truncates the inverted PSD. To truncate
        # the non-inverted PSD we give it the inverted PSD to truncate and then
        # invert the output.
        psd = 1. / pycbc.psd.inverse_spectrum_truncation(
            1. / psd,
            FILTER_LENGTH * SAMPLE_RATE,
            low_frequency_cutoff=low_frequency_cutoff,
            trunc_method='hann')
        psd = FrequencySeries(psd, dtype=complex_same_precision_as(psd))
        # Zero-pad the time-domain PSD to desired length. Zeroes must be added
        # in the middle, so some rolling between a resize is used.
        psd = psd.to_timeseries()
        psd.roll(SAMPLE_RATE * FILTER_LENGTH)
        psd.resize(wn_dur * SAMPLE_RATE)
        psd.roll(-SAMPLE_RATE * FILTER_LENGTH)
        # As time series is still mirrored the complex frequency components are
        # 0. But convert to real by using abs as in inverse_spectrum_truncate
        psd = psd.to_frequencyseries()
    else:
        wn_dur = (end_time - start_time) + 2 * FILTER_LENGTH
        psd = pycbc.psd.interpolate(psd, 1.0 / wn_dur)
        psd = 1. / pycbc.psd.inverse_spectrum_truncation(
            1. / psd,
            FILTER_LENGTH * SAMPLE_RATE,
            low_frequency_cutoff=low_frequency_cutoff,
            trunc_method='hann')
    asd = (psd.real())**0.5
    del psd
    white_noise = normal(start_time - FILTER_LENGTH,
                         end_time + FILTER_LENGTH,
                         seed=seed)
    white_noise = white_noise.to_frequencyseries()
    # Here we color. Do not want to duplicate memory here though so use '*='
    white_noise *= asd
    del asd
    colored = white_noise.to_timeseries()
    del white_noise
    return colored.time_slice(start_time, end_time)
예제 #15
0
def spintaylorf2(**kwds):
    """ Return a SpinTaylorF2 waveform using CUDA to generate the phase and amplitude
    """
    #####Pull out the input arguments#####
    f_lower = double(kwds['f_lower'])
    delta_f = double(kwds['delta_f'])
    distance = double(kwds['distance'])
    mass1 = double(kwds['mass1'])
    mass2 = double(kwds['mass2'])
    spin1x = double(kwds['spin1x'])
    spin1y = double(kwds['spin1y'])
    spin1z = double(kwds['spin1z'])
    phi0 = double(kwds['coa_phase'])  #Orbital Phase at coalescence
    phase_order = int(kwds['phase_order'])
    amplitude_order = int(kwds['amplitude_order'])
    inclination = double(kwds['inclination'])
    lnhatx = sin(inclination)
    lnhaty = 0.
    lnhatz = cos(inclination)
    psi = 0.

    tC = -1.0 / delta_f
    M = mass1 + mass2
    eta = mass1 * mass2 / (M * M)
    m_sec = M * lal.MTSUN_SI
    piM = lal.PI * m_sec

    vISCO = 1. / sqrt(6.)
    fISCO = vISCO * vISCO * vISCO / piM
    f_max = ceilpow2(fISCO)
    n = int(f_max / delta_f + 1)
    kmax = int(fISCO / delta_f)
    kmin = int(numpy.ceil(f_lower / delta_f))
    kmax = kmax if (kmax < n) else n

    #####Calculate the Orientation#####
    v0 = pow(piM * kmin * delta_f, 1. / 3)
    chi = sqrt(spin1x**2 + spin1y**2 + spin1z**2)
    kappa = (lnhatx * spin1x + lnhaty * spin1y + lnhatz * spin1z) / chi if (
        chi > 0.) else 1.
    Jx0 = mass1 * mass2 * lnhatx / v0 + mass1 * mass1 * spin1x
    Jy0 = mass1 * mass2 * lnhaty / v0 + mass1 * mass1 * spin1y
    Jz0 = mass1 * mass2 * lnhatz / v0 + mass1 * mass1 * spin1z
    thetaJ = acos(Jz0 / sqrt(Jx0**2 + Jy0**2 + Jz0**2))
    psiJ = atan2(Jy0, -Jx0)  # FIXME: check that Jy0 and Jx0 are not both 0
    # Rotate Lnhat back to frame where J is along z, to figure out initial alpha
    rotLx = lnhatx * cos(thetaJ) * cos(psiJ) - lnhaty * cos(thetaJ) * sin(
        psiJ) + lnhatz * sin(thetaJ)
    rotLy = lnhatx * sin(psiJ) + lnhaty * cos(psiJ)
    alpha0 = atan2(rotLy,
                   rotLx)  # FIXME: check that rotLy and rotLx are not both 0
    psiJ_P = psiJ + psi
    psiJ_C = psiJ + psi + lal.PI / 4.

    #####Calculate the Coefficients#####
    #quadparam = 1.
    gamma0 = mass1 * chi / mass2
    #Calculate the spin corrections
    # FIXME should use pycbc's function, but sigma has different expression
    # in Andy's code, double check
    # pn_beta, pn_sigma, pn_gamma = pycbc.pnutils.mass1_mass2_spin1z_spin2z_to_beta_sigma_gamma(
    #                               mass1, mass2, chi*kappa, 0) # FIXME: spin2 is taken to be 0
    pn_beta = (113. * mass1 / (12. * M) - 19. * eta / 6.) * chi * kappa
    pn_sigma = (
        (5. * (3. * kappa * kappa - 1.) / 2.) +
        (7. - kappa * kappa) / 96.) * (mass1 * mass1 * chi * chi / M / M)
    pn_gamma = (5. * (146597. + 7056. * eta) * mass1 /
                (2268. * M) - 10. * eta *
                (1276. + 153. * eta) / 81.) * chi * kappa
    prec_fac0 = 5. * (4. + 3. * mass2 / mass1) / 64.
    dtdv2 = 743. / 336. + 11. * eta / 4.
    dtdv3 = -4. * lal.PI + pn_beta
    dtdv4 = 3058673. / 1016064. + 5429. * eta / 1008. + 617. * eta * eta / 144. - pn_sigma
    dtdv5 = (-7729. / 672. + 13. * eta / 8.) * lal.PI + 9. * pn_gamma / 40.

    #####Calculate the Initial Euler Angles alpha_ref, beta_ref=0 and zeta_ref#####
    gam = gamma0 * v0
    sqrtfac = sqrt(1. + 2. * kappa * gam + gam * gam)
    logv0 = log(v0)
    logfac1 = log(1. + kappa * gam + sqrtfac)
    logfac2 = log(kappa + gam + sqrtfac)
    v02 = v0 * v0
    v03 = v0 * v02
    kappa2 = kappa * kappa
    kappa3 = kappa2 * kappa
    gamma02 = gamma0 * gamma0
    gamma03 = gamma02 * gamma0

    alpha_ref = prec_fac0 * (
        logfac2 * (dtdv2 * gamma0 + dtdv3 * kappa - dtdv5 * kappa /
                   (2. * gamma02) + dtdv4 / (2. * gamma0) - dtdv4 * kappa2 /
                   (2. * gamma0) + (dtdv5 * kappa3) /
                   (2. * gamma02)) + logfac1 *
        (-dtdv2 * gamma0 * kappa - dtdv3 + kappa * gamma03 / 2. -
         gamma03 * kappa3 / 2.) + logv0 *
        (dtdv2 * gamma0 * kappa + dtdv3 - kappa * gamma03 / 2. +
         gamma03 * kappa3 / 2.) + sqrtfac *
        (dtdv3 + dtdv4 * v0 / 2. + dtdv5 / gamma02 / 3. + dtdv4 * kappa /
         (2. * gamma0) + dtdv5 * kappa * v0 / (6. * gamma0) - dtdv5 * kappa2 /
         (2. * gamma02) - 1 / (3. * v03) - gamma0 * kappa /
         (6. * v02) - dtdv2 / v0 - gamma02 / (3. * v0) + gamma02 * kappa2 /
         (2. * v0) + dtdv5 * v02 / 3.)) - alpha0

    zeta_ref = prec_fac0 * (
        dtdv3 * gamma0 * kappa * v0 + dtdv4 * v0 + logfac2 *
        (-dtdv2 * gamma0 - dtdv3 * kappa + dtdv5 * kappa /
         (2. * gamma02) - dtdv4 / (2. * gamma0) + dtdv4 * kappa2 /
         (2. * gamma0) - dtdv5 * kappa3 / (2. * gamma02)) + logv0 *
        (kappa * gamma03 / 2. - gamma03 * kappa3 / 2.) + logfac1 *
        (dtdv2 * gamma0 * kappa + dtdv3 - kappa * gamma03 / 2. +
         gamma03 * kappa3 / 2.) - 1 / (3. * v03) - gamma0 * kappa /
        (2. * v02) - dtdv2 / v0 + dtdv4 * gamma0 * kappa * v02 / 2. +
        dtdv5 * v02 / 2. + sqrtfac *
        (-dtdv3 - dtdv4 * v0 / 2. - dtdv5 / (3. * gamma02) - dtdv4 * kappa /
         (2. * gamma0) - dtdv5 * kappa * v0 / (6. * gamma0) + dtdv5 * kappa2 /
         (2. * gamma02) + 1 / (3. * v03) + gamma0 * kappa /
         (6. * v02) + dtdv2 / v0 + gamma02 / (3. * v0) - gamma02 * kappa2 /
         (2. * v0) - dtdv5 * v02 / 3.) + dtdv5 * gamma0 * kappa * v03 / 3.)

    #####Calculate the Complex sideband factors, mm=2 is first entry#####
    RE_SBfac0 = (1. + cos(thetaJ)**2) / 2.
    RE_SBfac1 = sin(2. * thetaJ)
    RE_SBfac2 = 3. * sin(thetaJ)**2
    RE_SBfac3 = -sin(2. * thetaJ)
    RE_SBfac4 = (1. + cos(thetaJ)**2) / 2.
    IM_SBfac0 = -cos(thetaJ)
    IM_SBfac1 = -2. * sin(thetaJ)
    IM_SBfac2 = 0.
    IM_SBfac3 = -2. * sin(thetaJ)
    IM_SBfac4 = cos(thetaJ)

    #####Calculate the PN terms # FIXME replace with functions in lalsimulation #####
    theta = -11831. / 9240.
    lambdaa = -1987. / 3080.0
    pfaN = 3.0 / (128.0 * eta)
    pfa2 = 5.0 * (743.0 / 84 + 11.0 * eta) / 9.0
    pfa3 = -16.0 * lal.PI + 4.0 * pn_beta
    pfa4 = 5.0*(3058.673/7.056 + 5429.0/7.0 * eta + 617.0 * eta*eta)/72.0 - \
            10.0*pn_sigma
    pfa5 = 5.0 / 9.0 * (7729.0 / 84.0 - 13.0 * eta) * lal.PI - pn_gamma
    pfl5 = 5.0 / 3.0 * (7729.0 / 84.0 - 13.0 * eta) * lal.PI - pn_gamma * 3
    pfa6 = (11583.231236531/4.694215680 - 640.0/3.0 * lal.PI * lal.PI- \
            6848.0/21.0*lal.GAMMA) + \
            eta * (-15335.597827/3.048192 + 2255./12. * lal.PI * \
            lal.PI - 1760./3.*theta +12320./9.*lambdaa) + \
            eta*eta * 76055.0/1728.0 - \
            eta*eta*eta*  127825.0/1296.0
    pfl6 = -6848.0 / 21.0
    pfa7 = lal.PI * 5.0/756.0 * ( 15419335.0/336.0 + 75703.0/2.0 * eta - \
            14809.0 * eta*eta)

    FTaN = 32.0 * eta * eta / 5.0
    FTa2 = -(12.47 / 3.36 + 3.5 / 1.2 * eta)
    FTa3 = 4.0 * lal.PI
    FTa4 = -(44.711 / 9.072 - 92.71 / 5.04 * eta - 6.5 / 1.8 * eta * eta)
    FTa5 = -(81.91 / 6.72 + 58.3 / 2.4 * eta) * lal.PI
    FTa6 = (664.3739519 / 6.9854400 + 16.0 / 3.0 * lal.PI * lal.PI -
            17.12 / 1.05 * lal.GAMMA +
            (4.1 / 4.8 * lal.PI * lal.PI - 134.543 / 7.776) * eta -
            94.403 / 3.024 * eta * eta - 7.75 / 3.24 * eta * eta * eta)
    FTl6 = -8.56 / 1.05
    FTa7 = -(162.85/5.04 - 214.745/1.728 * eta - 193.385/3.024 * eta*eta) \
            * lal.PI

    dETaN = 2 * -eta / 2.0
    dETa1 = 2 * -(3.0 / 4.0 + 1.0 / 12.0 * eta)
    dETa2 = 3 * -(27.0 / 8.0 - 19.0 / 8.0 * eta + 1. / 24.0 * eta * eta)
    dETa3 = 4 * -(67.5 / 6.4 -
                  (344.45 / 5.76 - 20.5 / 9.6 * lal.PI * lal.PI) * eta +
                  15.5 / 9.6 * eta * eta + 3.5 / 518.4 * eta * eta * eta)

    amp0 = -4. * mass1 * mass2 / (1.0e+06 * distance * lal.PC_SI ) * \
                    lal.MRSUN_SI * lal.MTSUN_SI * sqrt(lal.PI/12.0)

    htildeP = FrequencySeries(zeros(n, dtype=complex128),
                              delta_f=delta_f,
                              copy=False)
    htildeC = FrequencySeries(zeros(n, dtype=complex128),
                              delta_f=delta_f,
                              copy=False)
    spintaylorf2_kernel(htildeP.data[kmin:kmax], htildeC.data[kmin:kmax], kmin,
                        phase_order, amplitude_order, delta_f, piM, pfaN, pfa2,
                        pfa3, pfa4, pfa5, pfl5, pfa6, pfl6, pfa7, FTaN, FTa2,
                        FTa3, FTa4, FTa5, FTa6, FTl6, FTa7, dETaN, dETa1,
                        dETa2, dETa3, amp0, tC, phi0, kappa, prec_fac0,
                        alpha_ref, zeta_ref, dtdv2, dtdv3, dtdv4, dtdv5,
                        RE_SBfac0, RE_SBfac1, RE_SBfac2, RE_SBfac3, RE_SBfac4,
                        IM_SBfac0, IM_SBfac1, IM_SBfac2, IM_SBfac3, IM_SBfac4,
                        psiJ_P, psiJ_C, gamma0)

    return htildeP, htildeC
예제 #16
0
    def __init__(self,
                 low_frequency_cutoff,
                 high_frequency_cutoff,
                 snr_threshold,
                 tlen,
                 delta_f,
                 dtype,
                 segment_list,
                 template_output,
                 use_cluster,
                 downsample_factor=1,
                 upsample_threshold=1,
                 upsample_method='pruned_fft',
                 gpu_callback_method='none'):
        """ Create a matched filter engine.

        Parameters
        ----------
        low_frequency_cutoff : {None, float}, optional
            The frequency to begin the filter calculation. If None, begin at the
            first frequency after DC.
        high_frequency_cutoff : {None, float}, optional
            The frequency to stop the filter calculation. If None, continue to the
            the nyquist frequency.
        snr_threshold : float
            The minimum snr to return when filtering
        segment_list : list
            List of FrequencySeries that are the Fourier-transformed data segments
        template_output : complex64
            Array of memory given as the 'out' parameter to waveform.FilterBank
        use_cluster : boolean
            If true, cluster triggers above threshold using a window; otherwise,
            only apply a threshold.
        downsample_factor : {1, int}, optional
            The factor by which to reduce the sample rate when doing a heirarchical
            matched filter
        upsample_threshold : {1, float}, optional
            The fraction of the snr_threshold to trigger on the subsampled filter.
        upsample_method : {pruned_fft, str}
            The method to upsample or interpolate the reduced rate filter.
        """
        # Assuming analysis time is constant across templates and segments, also
        # delta_f is constant across segments.
        self.tlen = tlen
        self.flen = self.tlen / 2 + 1
        self.delta_f = delta_f
        self.dtype = dtype
        self.snr_threshold = snr_threshold
        self.flow = low_frequency_cutoff
        self.fhigh = high_frequency_cutoff
        self.gpu_callback_method = gpu_callback_method

        if downsample_factor == 1:
            self.snr_mem = zeros(self.tlen, dtype=self.dtype)
            self.corr_mem = zeros(self.tlen, dtype=self.dtype)
            self.segments = segment_list

            if use_cluster:
                self.matched_filter_and_cluster = self.full_matched_filter_and_cluster
                # setup the threasholding/clustering operations for each segment
                self.threshold_and_clusterers = []
                for seg in self.segments:
                    thresh = events.ThresholdCluster(self.snr_mem[seg.analyze])
                    self.threshold_and_clusterers.append(thresh)
            else:
                self.matched_filter_and_cluster = self.full_matched_filter_thresh_only

            # Assuming analysis time is constant across templates and segments, also
            # delta_f is constant across segments.
            self.htilde = template_output
            self.kmin, self.kmax = get_cutoff_indices(self.flow, self.fhigh,
                                                      self.delta_f, self.tlen)

            # Set up the correlation operations for each analysis segment
            corr_slice = slice(self.kmin, self.kmax)
            self.correlators = []
            for seg in self.segments:
                corr = Correlator(self.htilde[corr_slice], seg[corr_slice],
                                  self.corr_mem[corr_slice])
                self.correlators.append(corr)

            # setup up the ifft we will do
            self.ifft = IFFT(self.corr_mem, self.snr_mem)

        elif downsample_factor >= 1:
            self.matched_filter_and_cluster = self.heirarchical_matched_filter_and_cluster
            self.downsample_factor = downsample_factor
            self.upsample_method = upsample_method
            self.upsample_threshold = upsample_threshold

            N_full = self.tlen
            N_red = N_full / downsample_factor
            self.kmin_full, self.kmax_full = get_cutoff_indices(
                self.flow, self.fhigh, self.delta_f, N_full)

            self.kmin_red, _ = get_cutoff_indices(self.flow, self.fhigh,
                                                  self.delta_f, N_red)

            if self.kmax_full < N_red:
                self.kmax_red = self.kmax_full
            else:
                self.kmax_red = N_red - 1

            self.snr_mem = zeros(N_red, dtype=self.dtype)
            self.corr_mem_full = FrequencySeries(zeros(N_full,
                                                       dtype=self.dtype),
                                                 delta_f=self.delta_f)
            self.corr_mem = Array(self.corr_mem_full[0:N_red], copy=False)
            self.inter_vec = zeros(N_full, dtype=self.dtype)

        else:
            raise ValueError("Invalid downsample factor")
예제 #17
0
def spa_tmplt(**kwds):
    """ Generate a minimal TaylorF2 approximant with optimations for the sin/cos
    """
    # Pull out the input arguments
    f_lower = kwds['f_lower']
    delta_f = kwds['delta_f']
    distance = kwds['distance']
    mass1 = kwds['mass1']
    mass2 = kwds['mass2']
    s1z = kwds['spin1z']
    s2z = kwds['spin2z']
    phase_order = int(kwds['phase_order'])
    #amplitude_order = int(kwds['amplitude_order'])
    spin_order = int(kwds['spin_order'])

    if 'out' in kwds:
        out = kwds['out']
    else:
        out = None

    amp_factor = spa_amplitude_factor(mass1=mass1, mass2=mass2) / distance

    lal_pars = lal.CreateDict()
    if phase_order != -1:
        lalsimulation.SimInspiralWaveformParamsInsertPNPhaseOrder(
            lal_pars, phase_order)

    if spin_order != -1:
        lalsimulation.SimInspiralWaveformParamsInsertPNSpinOrder(
            lal_pars, spin_order)

    #Calculate the PN terms
    phasing = lalsimulation.SimInspiralTaylorF2AlignedPhasing(
        float(mass1), float(mass2), float(s1z), float(s2z), lal_pars)

    pfaN = phasing.v[0]
    pfa2 = phasing.v[2] / pfaN
    pfa3 = phasing.v[3] / pfaN
    pfa4 = phasing.v[4] / pfaN
    pfa5 = phasing.v[5] / pfaN
    pfa6 = (phasing.v[6] - phasing.vlogv[6] * log(4)) / pfaN
    pfa7 = phasing.v[7] / pfaN

    pfl5 = phasing.vlogv[5] / pfaN
    pfl6 = phasing.vlogv[6] / pfaN

    piM = lal.PI * (mass1 + mass2) * lal.MTSUN_SI

    kmin = int(f_lower / float(delta_f))

    vISCO = 1. / sqrt(6.)
    fISCO = vISCO * vISCO * vISCO / piM
    kmax = int(fISCO / delta_f)
    f_max = ceilpow2(fISCO)
    n = int(f_max / delta_f) + 1

    if not out:
        htilde = FrequencySeries(zeros(n, dtype=numpy.complex64),
                                 delta_f=delta_f,
                                 copy=False)
    else:
        if type(out) is not Array:
            raise TypeError("Output must be an instance of Array")
        if len(out) < kmax:
            kmax = len(out)
        if out.dtype != complex64:
            raise TypeError("Output array is the wrong dtype")
        htilde = FrequencySeries(out, delta_f=delta_f, copy=False)

    spa_tmplt_engine(htilde[kmin:kmax], kmin, phase_order, delta_f, piM, pfaN,
                     pfa2, pfa3, pfa4, pfa5, pfl5, pfa6, pfl6, pfa7,
                     amp_factor)
    return htilde
예제 #18
0
filter_n = filter_N / 2 + 1
filter_delta_f = 1.0 / float(options.filter_signal_length)

print("Number of Signal Waveforms: ", len(signal_table))
print("Number of Templates       : ", len(template_table))

print("Reading and Interpolating PSD")
if options.asd_file:
    psd = pycbc.psd.read.from_txt(options.asd_file, filter_n, filter_delta_f,
                                  options.filter_low_frequency_cutoff)
elif options.psd:
    psd = pycbc.psd.analytic.from_string(options.psd, filter_n, filter_delta_f,
                                         options.filter_low_frequency_cutoff)

psd *= DYN_RANGE_FAC**2
psd = FrequencySeries(psd, delta_f=psd.delta_f, dtype=float32)

with ctx:
    print("Pregenerating Signals")
    signals = []
    index = 0
    for signal_params in signal_table:
        index += 1
        update_progress(index / len(signal_table))
        stilde = get_waveform(options.signal_approximant,
                              options.signal_phase_order,
                              options.signal_amplitude_order, signal_params,
                              options.signal_start_frequency,
                              options.filter_sample_rate, filter_N)
        s_norm = sigmasq(
            stilde,
예제 #19
0
    def template_segment_checker(self, bank, t_num, segment, start_time):
        """Test if injections in segment are worth filtering with template.

        Using the current template, current segment, and injections within that
        segment. Test if the injections and sufficiently "similar" to any of
        the injections to justify actually performing a matched-filter call.
        Ther are two parts to this test: First we check if the chirp time of
        the template is within a provided window of any of the injections. If
        not then stop here, it is not worth filtering this template, segment
        combination for this injection set. If this check passes we compute a
        match between a coarse representation of the template and a coarse
        representation of each of the injections. If that match is above a
        user-provided value for any of the injections then filtering can
        proceed. This is currently only available if using frequency-domain
        templates.

        Parameters
        -----------
        FIXME

        Returns
        --------
        FIXME
        """
        if not self.enabled:
            # If disabled, always filter (ie. return True)
            return True

        # Get times covered by segment analyze
        sample_rate = 2. * (len(segment) - 1) * segment.delta_f
        cum_ind = segment.cumulative_index
        diff = segment.analyze.stop - segment.analyze.start
        seg_start_time = cum_ind / sample_rate + start_time
        seg_end_time = (cum_ind + diff) / sample_rate + start_time
        # And add buffer
        seg_start_time = seg_start_time - self.seg_buffer
        seg_end_time = seg_end_time + self.seg_buffer

        # Chirp time test
        if self.chirp_time_window is not None:
            m1 = bank.table[t_num]['mass1']
            m2 = bank.table[t_num]['mass2']
            tau0_temp, _ = mass1_mass2_to_tau0_tau3(m1, m2, self.f_lower)
            for inj in self.injection_params.table:
                end_time = inj.geocent_end_time + \
                    1E-9 * inj.geocent_end_time_ns
                if not (seg_start_time <= end_time <= seg_end_time):
                    continue
                tau0_inj, _ = \
                    mass1_mass2_to_tau0_tau3(inj.mass1, inj.mass2,
                                             self.f_lower)
                tau_diff = abs(tau0_temp - tau0_inj)
                if tau_diff <= self.chirp_time_window:
                    break
            else:
                # Get's here if all injections are outside chirp-time window
                return False

        # Coarse match test
        if self.match_threshold:
            if self._short_template_mem is None:
                # Set the memory for the short templates
                wav_len = 1 + int(
                    self.coarsematch_fmax / self.coarsematch_deltaf)
                self._short_template_mem = zeros(wav_len, dtype=np.complex64)

            # Set the current short PSD to red_psd
            try:
                red_psd = self._short_psd_storage[id(segment.psd)]
            except KeyError:
                # PSD doesn't exist yet, so make it!
                curr_psd = segment.psd.numpy()
                step_size = int(self.coarsematch_deltaf / segment.psd.delta_f)
                max_idx = int(self.coarsematch_fmax / segment.psd.delta_f) + 1
                red_psd_data = curr_psd[:max_idx:step_size]
                red_psd = FrequencySeries(
                    red_psd_data,  #copy=False,
                    delta_f=self.coarsematch_deltaf)
                self._short_psd_storage[id(curr_psd)] = red_psd

            # Set htilde to be the current short template
            if not t_num == self._short_template_id:
                # Set the memory for the short templates if unset
                if self._short_template_mem is None:
                    wav_len = 1 + int(
                        self.coarsematch_fmax / self.coarsematch_deltaf)
                    self._short_template_mem = zeros(wav_len,
                                                     dtype=np.complex64)
                # Generate short waveform
                htilde = bank.generate_with_delta_f_and_max_freq(
                    t_num,
                    self.coarsematch_fmax,
                    self.coarsematch_deltaf,
                    low_frequency_cutoff=bank.table[t_num].f_lower,
                    cached_mem=self._short_template_mem)
                self._short_template_id = t_num
                self._short_template_wav = htilde
            else:
                htilde = self._short_template_wav

            for inj in self.injection_params.table:
                end_time = inj.geocent_end_time + \
                    1E-9 * inj.geocent_end_time_ns
                if not (seg_start_time < end_time < seg_end_time):
                    continue
                curr_inj = self.short_injections[inj.simulation_id]
                o, _ = match(htilde,
                             curr_inj,
                             psd=red_psd,
                             low_frequency_cutoff=self.f_lower)
                if o > self.match_threshold:
                    break
            else:
                # Get's here if all injections are outside match threshold
                return False

        return True
예제 #20
0
def fd_decompress(amp,
                  phase,
                  sample_frequencies,
                  out=None,
                  df=None,
                  f_lower=None,
                  interpolation='linear'):
    """Decompresses an FD waveform using the given amplitude, phase, and the
    frequencies at which they are sampled at.

    Parameters
    ----------
    amp : array
        The amplitude of the waveform at the sample frequencies.
    phase : array
        The phase of the waveform at the sample frequencies.
    sample_frequencies : array
        The frequency (in Hz) of the waveform at the sample frequencies.
    out : {None, FrequencySeries}
        The output array to save the decompressed waveform to. If this contains
        slots for frequencies > the maximum frequency in sample_frequencies,
        the rest of the values are zeroed. If not provided, must provide a df.
    df : {None, float}
        The frequency step to use for the decompressed waveform. Must be
        provided if out is None.
    f_lower : {None, float}
        The frequency to start the decompression at. If None, will use whatever
        the lowest frequency is in sample_frequencies. All values at
        frequencies less than this will be 0 in the decompressed waveform.
    interpolation : {'linear', str}
        The interpolation to use for the amplitude and phase. Default is
        'linear'. If 'linear' a custom interpolater is used. Otherwise,
        ``scipy.interpolate.interp1d`` is used; for other options, see
        possible values for that function's ``kind`` argument.

    Returns
    -------
    out : FrqeuencySeries
        If out was provided, writes to that array. Otherwise, a new
        FrequencySeries with the decompressed waveform.
    """
    precision = _precision_map[sample_frequencies.dtype.name]
    if _precision_map[amp.dtype.name] != precision or \
            _precision_map[phase.dtype.name] != precision:
        raise ValueError("amp, phase, and sample_points must all have the "
                         "same precision")
    if out is None:
        if df is None:
            raise ValueError("Either provide output memory or a df")
        hlen = int(numpy.ceil(sample_frequencies.max() / df + 1))
        out = FrequencySeries(numpy.zeros(hlen,
                                          dtype=_complex_dtypes[precision]),
                              copy=False,
                              delta_f=df)
    else:
        # check for precision compatibility
        if out.precision == 'double' and precision == 'single':
            raise ValueError("cannot cast single precision to double")
        df = out.delta_f
        hlen = len(out)
    if f_lower is None:
        imin = 0
        f_lower = sample_frequencies[0]
    else:
        if f_lower >= sample_frequencies.max():
            raise ValueError("f_lower is > than the maximum sample frequency")
        imin = int(numpy.searchsorted(sample_frequencies, f_lower))
    start_index = int(numpy.floor(f_lower / df))
    # interpolate the amplitude and the phase
    if interpolation == "linear":
        if precision == 'single':
            code = _linear_decompress_code32
        else:
            code = _linear_decompress_code
        # use custom interpolation
        sflen = len(sample_frequencies)
        h = numpy.array(out.data, copy=False)
        delta_f = float(df)
        inline(code, ['h', 'hlen', 'sflen', 'delta_f', 'sample_frequencies',
                      'amp', 'phase', 'start_index', 'imin'],
               extra_compile_args=[WEAVE_FLAGS + '-march=native -O3 -w'] +\
                                  omp_flags,
               libraries=omp_libs)
    else:
        # use scipy for fancier interpolation
        outfreq = out.sample_frequencies.numpy()
        amp_interp = interpolate.interp1d(sample_frequencies.numpy(),
                                          amp.numpy(),
                                          kind=interpolation,
                                          bounds_error=False,
                                          fill_value=0.,
                                          assume_sorted=True)
        phase_interp = interpolate.interp1d(sample_frequencies.numpy(),
                                            phase.numpy(),
                                            kind=interpolation,
                                            bounds_error=False,
                                            fill_value=0.,
                                            assume_sorted=True)
        A = amp_interp(outfreq)
        phi = phase_interp(outfreq)
        out.data[:] = A * numpy.cos(phi) + (1j) * A * numpy.sin(phi)
    return out
예제 #21
0
def get_two_pol_waveform_filter(outplus, outcross, template, **kwargs):
    """Return a frequency domain waveform filter for the specified approximant.
    Unlike get_waveform_filter this function returns both h_plus and h_cross
    components of the waveform, which are needed for searches where h_plus
    and h_cross are not related by a simple phase shift.
    """
    n = len(outplus)

    # If we don't have an inclination column alpha3 might be used
    if not hasattr(template, 'inclination') and 'inclination' not in kwargs:
        if hasattr(template, 'alpha3'):
            kwargs['inclination'] = template.alpha3

    input_params = props(template, **kwargs)

    if input_params['approximant'] in fd_approximants(_scheme.mgr.state):
        wav_gen = fd_wav[type(_scheme.mgr.state)]
        hp, hc = wav_gen[input_params['approximant']](**input_params)
        hp.resize(n)
        hc.resize(n)
        outplus[0:len(hp)] = hp[:]
        hp = FrequencySeries(outplus, delta_f=hp.delta_f, copy=False)
        outcross[0:len(hc)] = hc[:]
        hc = FrequencySeries(outcross, delta_f=hc.delta_f, copy=False)
        hp.chirp_length = get_waveform_filter_length_in_time(**input_params)
        hp.length_in_time = hp.chirp_length
        hc.chirp_length = hp.chirp_length
        hc.length_in_time = hp.length_in_time
        return hp, hc
    elif input_params['approximant'] in td_approximants(_scheme.mgr.state):
        # N: number of time samples required
        N = (n-1)*2
        delta_f = 1.0 / (N * input_params['delta_t'])
        wav_gen = td_wav[type(_scheme.mgr.state)]
        hp, hc = wav_gen[input_params['approximant']](**input_params)
        # taper the time series hp if required
        if 'taper' in input_params.keys() and \
                input_params['taper'] is not None:
            hp = wfutils.taper_timeseries(hp, input_params['taper'],
                                          return_lal=False)
            hc = wfutils.taper_timeseries(hc, input_params['taper'],
                                          return_lal=False)
        # total duration of the waveform
        tmplt_length = len(hp) * hp.delta_t
        # 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( hp.start_time )  # conversion from LIGOTimeGPS
        hp.resize(N)
        hc.resize(N)
        k_zero = int(hp.start_time / hp.delta_t)
        hp.roll(k_zero)
        hc.roll(k_zero)
        hp_tilde = FrequencySeries(outplus, delta_f=delta_f, copy=False)
        hc_tilde = FrequencySeries(outcross, delta_f=delta_f, copy=False)
        fft(hp.astype(real_same_precision_as(hp_tilde)), hp_tilde)
        fft(hc.astype(real_same_precision_as(hc_tilde)), hc_tilde)
        hp_tilde.length_in_time = tmplt_length
        hp_tilde.chirp_length = tChirp
        hc_tilde.length_in_time = tmplt_length
        hc_tilde.chirp_length = tChirp
        return hp_tilde, hc_tilde
    else:
        raise ValueError("Approximant %s not available" %
                            (input_params['approximant']))
예제 #22
0
파일: test_io_live.py 프로젝트: vahi/pycbc
    def do_test(self, n_ifos, n_ifos_followup):
        # choose a random selection of interferometers
        # n_ifos will be used to generate the simulated trigger
        # n_ifos_followup will be used as followup-only
        all_ifos = random.sample(self.possible_ifos, n_ifos + n_ifos_followup)
        trig_ifos = all_ifos[0:n_ifos]

        results = {
            'foreground/stat': np.random.uniform(4, 20),
            'foreground/ifar': np.random.uniform(0.01, 1000)
        }
        followup_data = {}
        for ifo in all_ifos:
            offset = 10000 + np.random.uniform(-0.02, 0.02)
            amplitude = np.random.uniform(4, 20)

            # generate a mock SNR time series with a peak
            n = 201
            dt = 1. / 2048.
            t = np.arange(n) * dt
            t_peak = dt * n / 2
            snr = np.exp(-(t - t_peak)**2 * 3e-3**-2) * amplitude
            snr_series = TimeSeries((snr + 1j * 0).astype(np.complex64),
                                    delta_t=dt,
                                    epoch=offset)

            # generate a mock PSD
            psd_samples = np.random.exponential(size=1024)
            psd = FrequencySeries(psd_samples, delta_f=1.)

            # fill in the various fields
            if ifo in trig_ifos:
                base = 'foreground/' + ifo + '/'
                results[base + 'end_time'] = t_peak + offset
                results[base + 'snr'] = amplitude
                results[base + 'sigmasq'] = np.random.uniform(1e6, 2e6)
            followup_data[ifo] = {'snr_series': snr_series, 'psd': psd}

        for ifo, k in itertools.product(trig_ifos, self.template):
            results['foreground/' + ifo + '/' + k] = self.template[k]

        kwargs = {
            'psds': {ifo: followup_data[ifo]['psd']
                     for ifo in all_ifos},
            'low_frequency_cutoff': 20.,
            'followup_data': followup_data
        }
        coinc = SingleCoincForGraceDB(trig_ifos, results, **kwargs)

        tempdir = tempfile.mkdtemp()

        coinc_file_name = os.path.join(tempdir, 'coinc.xml.gz')

        if GraceDb is not None:
            # pretend to upload the event to GraceDB.
            # The upload will fail, but it should not raise an exception
            # and it should still leave the event file around
            coinc.upload(coinc_file_name,
                         gracedb_server='localhost',
                         testing=True)
        else:
            # no GraceDb module, so just save the coinc file
            coinc.save(coinc_file_name)

        # read back and check the coinc document
        read_coinc = ligolw_utils.load_filename(coinc_file_name,
                                                verbose=False,
                                                contenthandler=ContentHandler)
        single_table = table.get_table(read_coinc,
                                       lsctables.SnglInspiralTable.tableName)
        self.assertEqual(len(single_table), len(all_ifos))
        coinc_table = table.get_table(read_coinc,
                                      lsctables.CoincInspiralTable.tableName)
        self.assertEqual(len(coinc_table), 1)

        # make sure lalseries can read the PSDs
        psd_doc = ligolw_utils.load_filename(
            coinc_file_name,
            verbose=False,
            contenthandler=lalseries.PSDContentHandler)
        psd_dict = lalseries.read_psd_xmldoc(psd_doc)
        self.assertEqual(set(psd_dict.keys()), set(all_ifos))

        shutil.rmtree(tempdir)
예제 #23
0
파일: ringdown.py 프로젝트: molodiuc/pycbc
def get_fd_lm(template=None, **kwargs):
    """Return frequency domain lm mode with a given number of overtones.

    Parameters
    ----------
    template: object
        An object that has attached properties. This can be used to substitute
        for keyword arguments. A common example would be a row in an xml table.
    final_mass : float
        Mass of the final black hole.
    final_spin : float
        Spin of the final black hole.
    l : int
        l mode (lm modes available: 22, 21, 33, 44, 55).
    m : int
        m mode (lm modes available: 22, 21, 33, 44, 55).
    nmodes: int
        Number of overtones desired (maximum n=8)
    amplmn : float
        Amplitude of the lmn overtone, as many as the number of nmodes.
    philmn : float
        Phase of the lmn overtone, as many as the number of nmodes.
    delta_f : {None, float}, optional
        The frequency step used to generate the ringdown.
        If None, it will be set to the inverse of the time at which the
        amplitude is 1/1000 of the peak amplitude (the minimum of all modes).
    f_lower: {None, float}, optional
        The starting frequency of the output frequency series.
        If None, it will be set to delta_f.
    f_final : {None, float}, optional
        The ending frequency of the output frequency series.
        If None, it will be set to the frequency at which the amplitude
        is 1/1000 of the peak amplitude (the maximum of all modes).

    Returns
    -------
    hplustilde: FrequencySeries
        The plus phase of a lm mode with n overtones in frequency domain.
    hcrosstilde: FrequencySeries
        The cross phase of a lm mode with n overtones in frequency domain.
    """

    input_params = props(template, lm_required_args, **kwargs)

    # Get required args
    amps, phis = lm_amps_phases(**input_params)
    final_mass = input_params.pop('final_mass')
    final_spin = input_params.pop('final_spin')
    l, m = input_params.pop('l'), input_params.pop('m')
    nmodes = input_params.pop('nmodes')
    if int(nmodes) == 0:
        raise ValueError('Number of overtones (nmodes) must be greater '
                         'than zero.')
    # The following may not be in input_params
    delta_f = input_params.pop('delta_f', None)
    f_lower = input_params.pop('f_lower', None)
    f_final = input_params.pop('f_final', None)

    if delta_f is None:
        delta_f = lm_deltaf(final_mass, final_spin,
                            ['%d%d%d' % (l, m, nmodes)])
    if f_final is None:
        f_final = lm_ffinal(final_mass, final_spin,
                            ['%d%d%d' % (l, m, nmodes)])
    kmax = int(f_final / delta_f) + 1

    outplus = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f)
    outcross = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f)

    f_0, tau = get_lm_f0tau(final_mass, final_spin, l, m, nmodes)
    for n in range(nmodes):
        hplus, hcross = get_fd_qnm(template=None,
                                   f_0=f_0[n],
                                   tau=tau[n],
                                   phi=phis['%d%d%d' % (l, m, n)],
                                   amp=amps['%d%d%d' % (l, m, n)],
                                   delta_f=delta_f,
                                   f_lower=f_lower,
                                   f_final=f_final)
        outplus.data += hplus.data
        outcross.data += hcross.data

    return outplus, outcross
예제 #24
0
def get_waveform(approximant,
                 phase_order,
                 amplitude_order,
                 spin_order,
                 template_params,
                 start_frequency,
                 sample_rate,
                 length,
                 datafile=None,
                 verbose=False):
    #{{{
    print("IN hERE")
    delta_t = 1. / sample_rate
    delta_f = 1. / length
    filter_N = int(length)
    filter_n = filter_N / 2 + 1
    if approximant in fd_approximants() and 'Eccentric' not in approximant:
        print("NORMAL FD WAVEFORM for", approximant)
        delta_f = sample_rate / length
        hplus, hcross = get_fd_waveform(template_params,
                                        approximant=approximant,
                                        spin_order=spin_order,
                                        phase_order=phase_order,
                                        delta_f=delta_f,
                                        f_lower=start_frequency,
                                        amplitude_order=amplitude_order)
    elif approximant in td_approximants() and 'Eccentric' not in approximant:
        print("NORMAL TD WAVEFORM for", approximant)
        hplus, hcross = get_td_waveform(template_params,
                                        approximant=approximant,
                                        spin_order=spin_order,
                                        phase_order=phase_order,
                                        delta_t=1.0 / sample_rate,
                                        f_lower=start_frequency,
                                        amplitude_order=amplitude_order)
    elif 'EccentricIMR' in approximant:
        #{{{
        # Legacy support
        import sys
        sys.path.append('/home/kuma/grav/kuma/src/Eccentric_IMR/Codes/Python/')
        import EccentricIMR as Ecc
        try:
            mass1 = getattr(template_params, 'mass1')
            mass2 = getattr(template_params, 'mass2')
        except:
            raise RuntimeError("template_params does not have mass1 or mass2!")
        try:
            ecc = getattr(template_params, 'alpha1')
            if 'E0' in approximant: ecc = 0
            anom = getattr(template_params, 'alpha2')
            inc = getattr(template_params, 'inclination')
            rtrans = getattr(template_params, 'alpha')
            beta = 0
        except:
            raise RuntimeError(\
                  "template_params does not have alpha{,1,2} or inclination")
        tol = 1.e-16
        fmin = start_frequency
        sample_rate = sample_rate
        #
        print(" Using phase order: %d" % phase_order, file=sys.stdout)
        sys.stdout.flush()
        hplus, hcross = Ecc.generate_eccentric_waveform(mass1, mass2,\
                            ecc, anom, inc, beta,\
                            tol,\
                            r_transition=rtrans,\
                            phase_order=phase_order,\
                            fmin=fmin,\
                            sample_rate=sample_rate,\
                            inspiral_only=False)
        #}}}
    elif 'EccentricInspiral' in approximant:
        #{{{
        # Legacy support
        import sys
        sys.path.append('/home/kuma/grav/kuma/src/Eccentric_IMR/Codes/Python/')
        import EccentricIMR as Ecc
        try:
            mass1 = getattr(template_params, 'mass1')
            mass2 = getattr(template_params, 'mass2')
        except:
            raise RuntimeError("template_params does not have mass1 or mass2!")
        try:
            ecc = getattr(template_params, 'alpha1')
            if 'E0' in approximant: ecc = 0
            anom = getattr(template_params, 'alpha2')
            inc = getattr(template_params, 'inclination')
            beta = getattr(template_params, 'alpha')
        except:
            raise RuntimeError(\
                  "template_params does not have alpha{,1,2} or inclination")
        tol = 1.e-16
        fmin = start_frequency
        sample_rate = sample_rate
        #
        hplus, hcross = Ecc.generate_eccentric_waveform(mass1, mass2,\
                            ecc, anom, inc, beta,\
                            tol,\
                            phase_order=phase_order,\
                            fmin=fmin,\
                            sample_rate=sample_rate,\
                            inspiral_only=True)
        #}}}
    elif 'EccentricFD' in approximant:
        #{{{
        # Legacy support
        import lalsimulation as ls
        import lal
        delta_f = sample_rate / length
        try:
            mass1 = getattr(template_params, 'mass1')
            mass2 = getattr(template_params, 'mass2')
        except:
            raise RuntimeError("template_params does not have mass1 or mass2!")
        try:
            ecc = getattr(template_params, 'alpha1')
            if 'E0' in approximant: ecc = 0
            anom = getattr(template_params, 'alpha2')
            inc = getattr(template_params, 'inclination')
        except:
            raise RuntimeError(\
                  "template_params does not have alpha{1,2} or inclination")
        eccPar = ls.SimInspiralCreateTestGRParam("inclination_azimuth", inc)
        ls.SimInspiralAddTestGRParam(eccPar, "e_min", ecc)
        fmin = start_frequency
        fmax = sample_rate / 2
        #
        thp, thc = ls.SimInspiralChooseFDWaveform(0, delta_f,\
                        mass1*lal.MSUN_SI, mass2*lal.MSUN_SI,\
                        0,0,0,0,0,0,\
                        fmin, fmax, 0, 1.e6 * lal.PC_SI,\
                        inc, 0, 0, None, eccPar, -1, 7, ls.EccentricFD)
        hplus = FrequencySeries(thp.data.data[:],
                                delta_f=thp.deltaF,
                                epoch=thp.epoch)
        hcross = FrequencySeries(thc.data.data[:],
                                 delta_f=thc.deltaF,
                                 epoch=thc.epoch)
        #}}}
    elif 'FromDataFile' in approximant:
        #{{{
        # Legacy support
        if not os.path.exists(datafile):
            raise IOError("File %s not found!" % datafile)
        if verbose:
            print("Reading from data file %s" % datafile)

        # Figure out waveform parameters from filename
        #q_value, M_value, w_value, _, _ = EA.get_q_m_e_pn_o_from_filename(datafile)
        q_value, M_value, w_value = EA.get_q_m_e_from_filename(datafile)

        # Read data, down-sample (assume data file is more finely sampled than
        # needed, i.e. interpolation is NOT supported, nor will be)
        data = np.loadtxt(datafile)
        dt = data[1, 0] - data[0, 0]
        delta_t = 1. / sample_rate
        downsample_ratio = delta_t / dt
        if not approx_equal(downsample_ratio, np.int(downsample_ratio)):
            raise RuntimeError(
                "Cannot handling resampling at a fractional factor = %e" %
                downsample_ratio)
        elif verbose:
            print("Downsampling by a factor of %d" % int(downsample_ratio))
        h_real = TimeSeries(data[::int(downsample_ratio), 1] / DYN_RANGE_FAC,
                            delta_t=delta_t)
        h_imag = TimeSeries(data[::int(downsample_ratio), 2] / DYN_RANGE_FAC,
                            delta_t=delta_t)

        if verbose:
            print("max, min,len of h_real = ", max(h_real.data),
                  min(h_real.data), len(h_real.data))

        # Compute Strain
        tmplt_pars = template_params
        wav = generate_detector_strain(tmplt_pars, h_real, h_imag)
        wav = extend_waveform_TimeSeries(wav, filter_N)

        # Return TimeSeries with (m1, m2, w_value)
        m1, m2 = mtotal_eta_to_mass1_mass2(M_value,
                                           q_value / (1. + q_value)**2)
        htilde = make_frequency_series(wav)
        htilde = extend_waveform_FrequencySeries(htilde, filter_n)

        if verbose:
            print("ISNAN(htilde from file) = ", np.any(np.isnan(htilde.data)))
        return htilde, [m1, m2, w_value, dt]
        #}}}
    else:
        raise IOError(".. APPROXIMANT %s not found.." % approximant)
    ##
    hvec = hplus
    htilde = make_frequency_series(hvec)
    htilde = extend_waveform_FrequencySeries(htilde, filter_n)
    #
    print("type of hplus, hcross = ", type(hplus.data), type(hcross.data))
    if any(isnan(hplus.data)) or any(isnan(hcross.data)):
        print("..### %s hplus or hcross have NANS!!" % approximant)
    #
    if any(isinf(hplus.data)) or any(isinf(hcross.data)):
        print("..### %s hplus or hcross have INFS!!" % approximant)
    #
    if any(isnan(htilde.data)):
        print("..### %s Fourier transform htilde has NANS!!" % approximant)
    #
    if any(isinf(htilde.data)):
        print("..### %s Fourier transform htilde has INFS!!" % approximant)
    #
    return htilde
예제 #25
0
def cbrt_lookup(vmax, delta):
    vec = numpy.arange(0, vmax * 1.2, delta)
    return FrequencySeries(vec**(1.0 / 3.0), delta_f=delta).astype(float32)
def imrphenomc_tmplt(**kwds):
    """ Return an IMRPhenomC waveform using CUDA to generate the phase and amplitude
      Main Paper: arXiv:1005.3306
    """
    # Pull out the input arguments
    f_min = float128(kwds['f_lower'])
    f_max = float128(kwds['f_final'])
    delta_f = float128(kwds['delta_f'])
    distance = float128(kwds['distance'])
    mass1 = float128(kwds['mass1'])
    mass2 = float128(kwds['mass2'])
    spin1z = float128(kwds['spin1z'])
    spin2z = float128(kwds['spin2z'])

    if 'out' in kwds:
        out = kwds['out']
    else:
        out = None

    # Calculate binary parameters
    M = mass1 + mass2
    eta = mass1 * mass2 / (M * M)
    Xi = (mass1 * spin1z / M) + (mass2 * spin2z / M)
    Xisum = 2. * Xi
    Xiprod = Xi * Xi
    Xi2 = Xi * Xi

    m_sec = M * lal.MTSUN_SI
    piM = lal.PI * m_sec

    ## The units of distance given as input is taken to pe Mpc. Converting to SI
    distance *= (
        1.0e6 * lal.PC_SI /
        (2. * sqrt(5. / (64. * lal.PI)) * M * lal.MRSUN_SI * M * lal.MTSUN_SI))

    # Check if the value of f_max is correctly given, else replace with the fCut
    # used in the PhenomB code in lalsimulation. The various coefficients come
    # from Eq.(4.18) of http://arxiv.org/pdf/0710.2335 and
    # Table I of http://arxiv.org/pdf/0712.0343
    if not f_max:
        f_max = (1.7086 * eta * eta - 0.26592 * eta + 0.28236) / piM

    # Transform the eta, chi to Lambda parameters, using Eq 5.14, Table II of Main
    # paper.
    z101 = -2.417e-03
    z102 = -1.093e-03
    z111 = -1.917e-02
    z110 = 7.267e-02
    z120 = -2.504e-01

    z201 = 5.962e-01
    z202 = -5.600e-02
    z211 = 1.520e-01
    z210 = -2.970e+00
    z220 = 1.312e+01

    z301 = -3.283e+01
    z302 = 8.859e+00
    z311 = 2.931e+01
    z310 = 7.954e+01
    z320 = -4.349e+02

    z401 = 1.619e+02
    z402 = -4.702e+01
    z411 = -1.751e+02
    z410 = -3.225e+02
    z420 = 1.587e+03

    z501 = -6.320e+02
    z502 = 2.463e+02
    z511 = 1.048e+03
    z510 = 3.355e+02
    z520 = -5.115e+03

    z601 = -4.809e+01
    z602 = -3.643e+02
    z611 = -5.215e+02
    z610 = 1.870e+03
    z620 = 7.354e+02

    z701 = 4.149e+00
    z702 = -4.070e+00
    z711 = -8.752e+01
    z710 = -4.897e+01
    z720 = 6.665e+02

    z801 = -5.472e-02
    z802 = 2.094e-02
    z811 = 3.554e-01
    z810 = 1.151e-01
    z820 = 9.640e-01

    z901 = -1.235e+00
    z902 = 3.423e-01
    z911 = 6.062e+00
    z910 = 5.949e+00
    z920 = -1.069e+01

    eta2 = eta * eta
    Xi2 = Xiprod

    # Calculate alphas, gamma, deltas from Table II and Eq 5.14 of Main paper
    a1 = z101 * Xi + z102 * Xi2 + z111 * eta * Xi + z110 * eta + z120 * eta2
    a2 = z201 * Xi + z202 * Xi2 + z211 * eta * Xi + z210 * eta + z220 * eta2
    a3 = z301 * Xi + z302 * Xi2 + z311 * eta * Xi + z310 * eta + z320 * eta2
    a4 = z401 * Xi + z402 * Xi2 + z411 * eta * Xi + z410 * eta + z420 * eta2
    a5 = z501 * Xi + z502 * Xi2 + z511 * eta * Xi + z510 * eta + z520 * eta2
    a6 = z601 * Xi + z602 * Xi2 + z611 * eta * Xi + z610 * eta + z620 * eta2

    g1 = z701 * Xi + z702 * Xi2 + z711 * eta * Xi + z710 * eta + z720 * eta2

    del1 = z801 * Xi + z802 * Xi2 + z811 * eta * Xi + z810 * eta + z820 * eta2
    del2 = z901 * Xi + z902 * Xi2 + z911 * eta * Xi + z910 * eta + z920 * eta2

    # Get the spin of the final BH
    afin = FinalSpin(Xi, eta)
    Q = Qa(abs(afin))

    # Get the fRD
    frd = fRD(abs(afin), M)
    Mfrd = frd * m_sec

    # Define the frequencies where SPA->PM->RD
    f1 = 0.1 * frd
    Mf1 = m_sec * f1
    f2 = frd
    Mf2 = m_sec * f2
    d1 = 0.005
    d2 = 0.005
    f0 = 0.98 * frd
    Mf0 = m_sec * f0
    d0 = 0.015

    # Now use this frequency for calculation of betas
    # calculate beta1 and beta2, that appear in Eq 5.7 in the main paper.
    b2 = ((-5./3.)* a1 * pow(Mfrd,(-8./3.)) - a2/(Mfrd*Mfrd) - \
      (a3/3.)*pow(Mfrd,(-4./3.)) + (2./3.)* a5 * pow(Mfrd,(-1./3.)) + a6)/eta

    psiPMrd = (a1 * pow(Mfrd,(-5./3.)) + a2/Mfrd + a3 * pow(Mfrd,(-1./3.)) + \
      a4 + a5 * pow(Mfrd,(2./3.)) + a6 * Mfrd)/eta
    b1 = psiPMrd - (b2 * Mfrd)

    ### Calculate the PN coefficients, Eq A3 - A5 of main paper ###
    pfaN = 3.0 / (128.0 * eta)
    pfa2 = (3715. / 756.) + (55. * eta / 9.0)
    pfa3 = -16.0 * lal.PI + (113. / 3.) * Xi - 38. * eta * Xisum / 3.
    pfa4 = (152.93365/5.08032) - 50.*Xi2 + eta*(271.45/5.04 + 1.25*Xiprod) + \
        3085.*eta2/72.
    pfa5 = lal.PI*(386.45/7.56 - 65.*eta/9.) - \
        Xi*(735.505/2.268 + 130.*eta/9.) + Xisum*(1285.0*eta/8.1 + 170.*eta2/9.) - \
        10.*Xi2*Xi/3. + 10.*eta*Xi*Xiprod
    pfa6 = 11583.231236531/4.694215680 - 640.0*lal.PI*lal.PI/3. - \
        6848.0*lal.GAMMA/21. - 684.8*log(64.)/6.3 + \
        eta*(2255.*lal.PI*lal.PI/12. - 15737.765635/3.048192) + \
        76.055*eta2/1.728 - (127.825*eta2*eta/1.296) + \
        2920.*lal.PI*Xi/3. - (175. - 1490.*eta)*Xi2/3. - \
        (1120.*lal.PI/3. - 1085.*Xi/3.)*eta*Xisum + \
        (269.45*eta/3.36 - 2365.*eta2/6.)*Xiprod

    pfa6log = -6848. / 63.

    pfa7 = lal.PI*(770.96675/2.54016 + 378.515*eta/1.512 - 740.45*eta2/7.56) - \
        Xi*(20373.952415/3.048192 + 1509.35*eta/2.24 - 5786.95*eta2/4.32) + \
        Xisum*(4862.041225*eta/1.524096 + 1189.775*eta2/1.008 - 717.05*eta2*eta/2.16 - 830.*eta*Xi2/3. + 35.*eta2*Xiprod/3.) - \
        560.*lal.PI*Xi2 + 20.*lal.PI*eta*Xiprod + \
        Xi2*Xi*(945.55/1.68 - 85.*eta) + Xi*Xiprod*(396.65*eta/1.68 + 255.*eta2)

    xdotaN = 64. * eta / 5.
    xdota2 = -7.43 / 3.36 - 11. * eta / 4.
    xdota3 = 4. * lal.PI - 11.3 * Xi / 1.2 + 19. * eta * Xisum / 6.
    xdota4 = 3.4103 / 1.8144 + 5 * Xi2 + eta * (13.661 / 2.016 -
                                                Xiprod / 8.) + 5.9 * eta2 / 1.8
    xdota5 = -lal.PI*(41.59/6.72 + 189.*eta/8.) - Xi*(31.571/1.008 - 116.5*eta/2.4) + \
          Xisum*(21.863*eta/1.008 - 79.*eta2/6.) - 3*Xi*Xi2/4. + \
          9.*eta*Xi*Xiprod/4.
    xdota6 = 164.47322263/1.39708800 - 17.12*lal.GAMMA/1.05 + \
          16.*lal.PI*lal.PI/3 - 8.56*log(16.)/1.05 + \
          eta*(45.1*lal.PI*lal.PI/4.8 - 561.98689/2.17728) + \
          5.41*eta2/8.96 - 5.605*eta*eta2/2.592 - 80.*lal.PI*Xi/3. + \
          eta*Xisum*(20.*lal.PI/3. - 113.5*Xi/3.6) + \
          Xi2*(64.153/1.008 - 45.7*eta/3.6) - \
          Xiprod*(7.87*eta/1.44 - 30.37*eta2/1.44)

    xdota6log = -856. / 105.

    xdota7 = -lal.PI*(4.415/4.032 - 358.675*eta/6.048 - 91.495*eta2/1.512) - \
          Xi*(252.9407/2.7216 - 845.827*eta/6.048 + 415.51*eta2/8.64) + \
          Xisum*(158.0239*eta/5.4432 - 451.597*eta2/6.048 + 20.45*eta2*eta/4.32 + 107.*eta*Xi2/6. - 5.*eta2*Xiprod/24.) + \
          12.*lal.PI*Xi2 - Xi2*Xi*(150.5/2.4 + eta/8.) + \
          Xi*Xiprod*(10.1*eta/2.4 + 3.*eta2/8.)

    AN = 8. * eta * sqrt(lal.PI / 5.)
    A2 = (-107. + 55. * eta) / 42.
    A3 = 2. * lal.PI - 4. * Xi / 3. + 2. * eta * Xisum / 3.
    A4 = -2.173 / 1.512 - eta * (10.69 / 2.16 -
                                 2. * Xiprod) + 2.047 * eta2 / 1.512
    A5 = -10.7 * lal.PI / 2.1 + eta * (3.4 * lal.PI / 2.1)

    A5imag = -24. * eta

    A6 = 270.27409/6.46800 - 8.56*lal.GAMMA/1.05 + \
      2.*lal.PI*lal.PI/3. + \
      eta*(4.1*lal.PI*lal.PI/9.6 - 27.8185/3.3264) - \
      20.261*eta2/2.772 + 11.4635*eta*eta2/9.9792 - \
      4.28*log(16.)/1.05

    A6log = -428. / 105.

    A6imag = 4.28 * lal.PI / 1.05

    ### Define other parameters needed by waveform generation ###
    kmin = int(f_min / delta_f)
    kmax = int(f_max / delta_f)
    n = kmax + 1

    if not out:
        htilde = FrequencySeries(zeros(n, dtype=numpy.complex128),
                                 delta_f=delta_f,
                                 copy=False)
    else:
        if type(out) is not Array:
            raise TypeError("Output must be an instance of Array")
        if len(out) < kmax:
            raise TypeError("Output array is too small")
        if out.dtype != complex64:
            raise TypeError("Output array is the wrong dtype")
        htilde = FrequencySeries(out, delta_f=delta_f, copy=False)

    phenomC_kernel(htilde.data[kmin:kmax], kmin, delta_f, eta, Xi, distance,
                   m_sec, piM, Mfrd, pfaN, pfa2, pfa3, pfa4, pfa5, pfa6,
                   pfa6log, pfa7, a1, a2, a3, a4, a5, a6, b1, b2, Mf1, Mf2,
                   Mf0, d1, d2, d0, xdota2, xdota3, xdota4, xdota5, xdota6,
                   xdota6log, xdota7, xdotaN, AN, A2, A3, A4, A5, A5imag, A6,
                   A6log, A6imag, g1, del1, del2, Q)
    hp = htilde
    hc = htilde * 1j
    return hp, hc
예제 #27
0
파일: compress.py 프로젝트: OliverEdy/pycbc
def fd_decompress(amp,
                  phase,
                  sample_frequencies,
                  out=None,
                  df=None,
                  f_lower=None,
                  interpolation='inline_linear'):
    """Decompresses an FD waveform using the given amplitude, phase, and the
    frequencies at which they are sampled at.

    Parameters
    ----------
    amp : array
        The amplitude of the waveform at the sample frequencies.
    phase : array
        The phase of the waveform at the sample frequencies.
    sample_frequencies : array
        The frequency (in Hz) of the waveform at the sample frequencies.
    out : {None, FrequencySeries}
        The output array to save the decompressed waveform to. If this contains
        slots for frequencies > the maximum frequency in sample_frequencies,
        the rest of the values are zeroed. If not provided, must provide a df.
    df : {None, float}
        The frequency step to use for the decompressed waveform. Must be
        provided if out is None.
    f_lower : {None, float}
        The frequency to start the decompression at. If None, will use whatever
        the lowest frequency is in sample_frequencies. All values at
        frequencies less than this will be 0 in the decompressed waveform.
    interpolation : {'inline_linear', str}
        The interpolation to use for the amplitude and phase. Default is
        'inline_linear'. If 'inline_linear' a custom interpolater is used.
        Otherwise, ``scipy.interpolate.interp1d`` is used; for other options,
        see possible values for that function's ``kind`` argument.

    Returns
    -------
    out : FrequencySeries
        If out was provided, writes to that array. Otherwise, a new
        FrequencySeries with the decompressed waveform.
    """
    precision = _precision_map[sample_frequencies.dtype.name]
    if _precision_map[amp.dtype.name] != precision or \
            _precision_map[phase.dtype.name] != precision:
        raise ValueError("amp, phase, and sample_points must all have the "
                         "same precision")

    if out is None:
        if df is None:
            raise ValueError("Either provide output memory or a df")
        hlen = int(numpy.ceil(sample_frequencies.max() / df + 1))
        out = FrequencySeries(numpy.zeros(hlen,
                                          dtype=_complex_dtypes[precision]),
                              copy=False,
                              delta_f=df)
    else:
        # check for precision compatibility
        if out.precision == 'double' and precision == 'single':
            raise ValueError("cannot cast single precision to double")
        df = out.delta_f
        hlen = len(out)
    if f_lower is None:
        imin = 0  # pylint:disable=unused-variable
        f_lower = sample_frequencies[0]
        start_index = 0
    else:
        if f_lower >= sample_frequencies.max():
            raise ValueError("f_lower is > than the maximum sample frequency")
        if f_lower < sample_frequencies.min():
            raise ValueError("f_lower is < than the minimum sample frequency")
        imin = int(
            numpy.searchsorted(sample_frequencies, f_lower, side='right')) - 1  # pylint:disable=unused-variable
        start_index = int(numpy.ceil(f_lower / df))
    if start_index >= hlen:
        raise ValueError('requested f_lower >= largest frequency in out')
    # interpolate the amplitude and the phase
    if interpolation == "inline_linear":
        # Call the scheme-dependent function
        inline_linear_interp(amp, phase, sample_frequencies, out, df, f_lower,
                             imin, start_index)
    else:
        # use scipy for fancier interpolation
        sample_frequencies = numpy.array(sample_frequencies)
        amp = numpy.array(amp)
        phase = numpy.array(phase)
        outfreq = out.sample_frequencies.numpy()
        amp_interp = interpolate.interp1d(sample_frequencies,
                                          amp,
                                          kind=interpolation,
                                          bounds_error=False,
                                          fill_value=0.,
                                          assume_sorted=True)
        phase_interp = interpolate.interp1d(sample_frequencies,
                                            phase,
                                            kind=interpolation,
                                            bounds_error=False,
                                            fill_value=0.,
                                            assume_sorted=True)
        A = amp_interp(outfreq)
        phi = phase_interp(outfreq)
        out.data[:] = A * numpy.cos(phi) + (1j) * A * numpy.sin(phi)
    return out
예제 #28
0
def calc_filt_psd_variation(strain, segment, short_segment, psd_long_segment,
                            psd_duration, psd_stride, psd_avg_method, low_freq,
                            high_freq):
    """ Calculates time series of PSD variability

    This function first splits the segment up into 512 second chunks. It
    then calculates the PSD over this 512 second. The PSD is used to
    to create a filter that is the composition of three filters:
    1. Bandpass filter between f_low and f_high.
    2. Weighting filter which gives the rough response of a CBC template.
    3. Whitening filter.
    Next it makes the convolution of this filter with the stretch of data.
    This new time series is given to the "mean_square" function, which
    computes the mean square of the timeseries within an 8 seconds window,
    once per second.
    The result, which is the variance of the S/N in that stride for the
    Parseval theorem, is then stored in a timeseries.

    Parameters
    ----------
    strain : TimeSeries
        Input strain time series to estimate PSDs
    segment : {float, 8}
        Duration of the segments for the mean square estimation in seconds.
    short_segment : {float, 0.25}
        Duration of the short segments for the outliers removal.
    psd_long_segment : {float, 512}
        Duration of the long segments for PSD estimation in seconds.
    psd_duration : {float, 8}
        Duration of FFT segments for long term PSD estimation, in seconds.
    psd_stride : {float, 4}
        Separation between FFT segments for long term PSD estimation, in
        seconds.
    psd_avg_method : {string, 'median'}
        Method for averaging PSD estimation segments.
    low_freq : {float, 20}
        Minimum frequency to consider the comparison between PSDs.
    high_freq : {float, 480}
        Maximum frequency to consider the comparison between PSDs.

    Returns
    -------
    psd_var : TimeSeries
        Time series of the variability in the PSD estimation
    """
    # Calculate strain precision
    if strain.precision == 'single':
        fs_dtype = numpy.float32
    elif strain.precision == 'double':
        fs_dtype = numpy.float64

    # Convert start and end times immediately to floats
    start_time = numpy.float(strain.start_time)
    end_time = numpy.float(strain.end_time)

    # Resample the data
    strain = resample_to_delta_t(strain, 1.0 / 2048)
    srate = int(strain.sample_rate)

    # Fix the step for the PSD estimation and the time to remove at the
    # edge of the time series.
    step = 1.0
    strain_crop = 8.0

    # Find the times of the long segments
    times_long = numpy.arange(
        start_time, end_time,
        psd_long_segment - 2 * strain_crop - segment + step)

    # Set up the empty time series for the PSD variation estimate
    ts_duration = end_time - start_time - 2 * strain_crop - segment + 1
    psd_var = TimeSeries(zeros(int(numpy.floor(ts_duration / step))),
                         delta_t=step,
                         copy=False,
                         epoch=start_time + strain_crop + segment)

    # Create a bandpass filter between low_freq and high_freq
    filt = sig.firwin(4 * srate, [low_freq, high_freq],
                      pass_zero=False,
                      window='hann',
                      nyq=srate / 2)
    filt.resize(int(psd_duration * srate))
    # Fourier transform the filter and take the absolute value to get
    # rid of the phase. Save the filter as a frequency series.
    filt = abs(rfft(filt))
    my_filter = FrequencySeries(filt,
                                delta_f=1. / psd_duration,
                                dtype=fs_dtype)

    ind = 0
    for tlong in times_long:
        # Calculate PSD for long segment
        if tlong + psd_long_segment <= float(end_time):
            astrain = strain.time_slice(tlong, tlong + psd_long_segment)
            plong = pycbc.psd.welch(
                astrain,
                seg_len=int(psd_duration * strain.sample_rate),
                seg_stride=int(psd_stride * strain.sample_rate),
                avg_method=psd_avg_method)
        else:
            astrain = strain.time_slice(tlong, end_time)
            plong = pycbc.psd.welch(
                strain.time_slice(end_time - psd_long_segment, end_time),
                seg_len=int(psd_duration * strain.sample_rate),
                seg_stride=int(psd_stride * strain.sample_rate),
                avg_method=psd_avg_method)

        # Make the weighting filter - bandpass, which weight by f^-7/6,
        # and whiten. The normalization is chosen so that the variance
        # will be one if this filter is applied to white noise which
        # already has a variance of one.
        freqs = FrequencySeries(plong.sample_frequencies,
                                delta_f=plong.delta_f,
                                epoch=plong.epoch,
                                dtype=fs_dtype)
        fweight = freqs**(-7. / 6.) * my_filter / numpy.sqrt(plong)
        fweight[0] = 0.
        norm = (sum(abs(fweight)**2) / (len(fweight) - 1.))**-0.5
        fweight = norm * fweight
        fwhiten = numpy.sqrt(2. / srate) / numpy.sqrt(plong)
        fwhiten[0] = 0.
        full_filt = sig.hann(int(psd_duration * srate)) * numpy.roll(
            irfft(fwhiten * fweight),
            int(psd_duration / 2) * srate)
        # Convolve the filter with long segment of data
        wstrain = TimeSeries(sig.fftconvolve(astrain, full_filt, mode='same'),
                             delta_t=strain.delta_t,
                             epoch=astrain.start_time)
        wstrain = wstrain[int(strain_crop * srate):-int(strain_crop * srate)]
        # compute the mean square of the chunk of data
        delta_t = wstrain.end_time.gpsSeconds - wstrain.start_time.gpsSeconds
        variation = mean_square(wstrain, delta_t, short_segment, segment)

        # Store variation value
        for i, val in enumerate(variation):
            psd_var[ind + i] = val

        ind = ind + len(variation)
    return psd_var
예제 #29
0
def welch(timeseries, seg_len=4096, seg_stride=2048, window='hann',
          avg_method='median', num_segments=None, require_exact_data_fit=False):
    """PSD estimator based on Welch's method.

    Parameters
    ----------
    timeseries : TimeSeries
        Time series for which the PSD is to be estimated.
    seg_len : int
        Segment length in samples.
    seg_stride : int
        Separation between consecutive segments, in samples.
    window : {'hann'}
        Function used to window segments before Fourier transforming.
    avg_method : {'median', 'mean', 'median-mean'}
        Method used for averaging individual segment PSDs.

    Returns
    -------
    psd : FrequencySeries
        Frequency series containing the estimated PSD.

    Raises
    ------
    ValueError
        For invalid choices of `seg_len`, `seg_stride` `window` and
        `avg_method` and for inconsistent combinations of len(`timeseries`),
        `seg_len` and `seg_stride`.

    Notes
    -----
    See arXiv:gr-qc/0509116 for details.
    """
    window_map = {
        'hann': numpy.hanning
    }

    # sanity checks
    if not window in window_map:
        raise ValueError('Invalid window')
    if not avg_method in ('mean', 'median', 'median-mean'):
        raise ValueError('Invalid averaging method')
    if type(seg_len) is not int or type(seg_stride) is not int \
        or seg_len <= 0 or seg_stride <= 0:
        raise ValueError('Segment length and stride must be positive integers')

    if timeseries.precision == 'single':
        fs_dtype = numpy.complex64
    elif timeseries.precision == 'double':
        fs_dtype = numpy.complex128
        
    num_samples = len(timeseries)
    if num_segments is None:
        num_segments = int(num_samples // seg_stride)
        # NOTE: Is this not always true?
        if (num_segments - 1) * seg_stride + seg_len > num_samples:
            num_segments -= 1

    if not require_exact_data_fit:
        data_len = (num_segments - 1) * seg_stride + seg_len

        # Get the correct amount of data
        if data_len < num_samples:
            diff = num_samples - data_len
            start = diff // 2
            end = num_samples - diff // 2
            # Want this to be integers so if diff is odd, catch it here.
            if diff % 2:
                start = start + 1

            timeseries = timeseries[start:end]
            num_samples = len(timeseries)
        if data_len > num_samples:
            err_msg = "I was asked to estimate a PSD on %d " %(data_len)
            err_msg += "data samples. However the data provided only contains "
            err_msg += "%d data samples." %(num_samples)

    if num_samples != (num_segments - 1) * seg_stride + seg_len:
        raise ValueError('Incorrect choice of segmentation parameters')
        
    w = Array(window_map[window](seg_len).astype(timeseries.dtype))

    # calculate psd of each segment
    delta_f = 1. / timeseries.delta_t / seg_len
    segment_tilde = FrequencySeries(numpy.zeros(seg_len / 2 + 1), \
        delta_f=delta_f, dtype=fs_dtype)

    segment_psds = []
    for i in xrange(num_segments):
        segment_start = i * seg_stride
        segment_end = segment_start + seg_len
        segment = timeseries[segment_start:segment_end]
        assert len(segment) == seg_len
        fft(segment * w, segment_tilde)
        seg_psd = abs(segment_tilde * segment_tilde.conj()).numpy()

        #halve the DC and Nyquist components to be consistent with TO10095
        seg_psd[0] /= 2
        seg_psd[-1] /= 2

        segment_psds.append(seg_psd)

    segment_psds = numpy.array(segment_psds)   

    if avg_method == 'mean':
        psd = numpy.mean(segment_psds, axis=0)
    elif avg_method == 'median':
        psd = numpy.median(segment_psds, axis=0) / median_bias(num_segments)
    elif avg_method == 'median-mean':
        odd_psds = segment_psds[::2]
        even_psds = segment_psds[1::2]
        odd_median = numpy.median(odd_psds, axis=0) / \
            median_bias(len(odd_psds))
        even_median = numpy.median(even_psds, axis=0) / \
            median_bias(len(even_psds))
        psd = (odd_median + even_median) / 2

    psd *= 2 * delta_f * seg_len / (w*w).sum()

    return FrequencySeries(psd, delta_f=delta_f, dtype=timeseries.dtype,
                           epoch=timeseries.start_time)
예제 #30
0
def matched_filter_core(template,
                        data,
                        psd=None,
                        low_frequency_cutoff=None,
                        high_frequency_cutoff=None,
                        h_norm=None,
                        out=None,
                        corr_out=None):
    """ Return the complex snr and normalization. 
    
    Return the complex snr, along with its associated normalization of the template,
    matched filtered against the data. 

    Parameters
    ----------
    template : TimeSeries or FrequencySeries 
        The template waveform
    data : TimeSeries or FrequencySeries 
        The strain data to be filtered.
    psd : {FrequencySeries}, optional
        The noise weighting of the filter.
    low_frequency_cutoff : {None, float}, optional
        The frequency to begin the filter calculation. If None, begin at the
        first frequency after DC.
    high_frequency_cutoff : {None, float}, optional
        The frequency to stop the filter calculation. If None, continue to the 
        the nyquist frequency.
    h_norm : {None, float}, optional
        The template normalization. If none, this value is calculated internally.
    out : {None, Array}, optional
        An array to use as memory for snr storage. If None, memory is allocated 
        internally.
    corr_out : {None, Array}, optional
        An array to use as memory for correlation storage. If None, memory is allocated 
        internally. If provided, management of the vector is handled externally by the
        caller. No zero'ing is done internally. 

    Returns
    -------
    snr : TimeSeries
        A time series containing the complex snr. 
    corrrelation: FrequencySeries
        A frequency series containing the correlation vector. 
    norm : float
        The normalization of the complex snr.  
    """
    if corr_out is not None:
        _qtilde = corr_out
    else:
        global _qtilde_t
        _qtilde = _qtilde_t

    htilde = make_frequency_series(template)
    stilde = make_frequency_series(data)

    if len(htilde) != len(stilde):
        raise ValueError("Length of template and data must match")

    N = (len(stilde) - 1) * 2
    kmin, kmax = get_cutoff_indices(low_frequency_cutoff,
                                    high_frequency_cutoff, stilde.delta_f, N)

    if out is None:
        _q = zeros(N, dtype=complex_same_precision_as(data))
    elif (len(out) == N) and type(out) is Array and out.kind == 'complex':
        _q = out
    else:
        raise TypeError('Invalid Output Vector: wrong length or dtype')

    if corr_out:
        pass
    elif (_qtilde is None) or (len(_qtilde) !=
                               N) or _qtilde.dtype != data.dtype:
        _qtilde_t = _qtilde = zeros(N, dtype=complex_same_precision_as(data))
    else:
        _qtilde.clear()

    correlate(htilde[kmin:kmax], stilde[kmin:kmax], _qtilde[kmin:kmax])

    if psd is not None:
        if isinstance(psd, FrequencySeries):
            if psd.delta_f == stilde.delta_f:
                _qtilde[kmin:kmax] /= psd[kmin:kmax]
            else:
                raise TypeError("PSD delta_f does not match data")
        else:
            raise TypeError("PSD must be a FrequencySeries")

    ifft(_qtilde, _q)

    if h_norm is None:
        h_norm = sigmasq(htilde, psd, low_frequency_cutoff,
                         high_frequency_cutoff)

    norm = (4.0 * stilde.delta_f) / sqrt(h_norm)
    delta_t = 1.0 / (N * stilde.delta_f)

    return (TimeSeries(_q, epoch=stilde._epoch, delta_t=delta_t, copy=False),
            FrequencySeries(_qtilde,
                            epoch=stilde._epoch,
                            delta_f=htilde.delta_f,
                            copy=False), norm)