Example #1
0
def ideal_tfr(iflaws, timestamps=None, n_fbins=None):
    """ideal_tfr

    :param iflaws:
    :param timestamps:
    :param n_fbins:
    :type iflaws:
    :type timestamps:
    :type n_fbins:
:return:
:rtype:
    """
    ifrow, ifcol = iflaws.shape
    timestamps, n_fbins = init_default_args(iflaws[0, :],
                                            timestamps=timestamps,
                                            n_fbins=n_fbins)

    tcol = timestamps.shape[0]

    tfr = np.zeros((n_fbins, tcol))
    for icol in xrange(tcol):
        ti = timestamps[icol]
        for fi in xrange(ifrow):
            if np.isnan(iflaws[fi, ti]):
                tfr[ti, fi] = np.nan
            else:
                tfr[int(np.round(iflaws[fi, ti] * 2 * (n_fbins - 1))),
                    icol] = 1
    freqs = np.arange(n_fbins, dtype=float) / n_fbins * 0.5
    return tfr, timestamps, freqs
Example #2
0
def ideal_tfr(iflaws, timestamps=None, n_fbins=None):
    """ideal_tfr

    :param iflaws:
    :param timestamps:
    :param n_fbins:
    :type iflaws:
    :type timestamps:
    :type n_fbins:
:return:
:rtype:
    """
    ifrow, ifcol = iflaws.shape
    timestamps, n_fbins = init_default_args(iflaws[0, :],
            timestamps=timestamps, n_fbins=n_fbins)

    tcol = timestamps.shape[0]

    tfr = np.zeros((n_fbins, tcol))
    for icol in xrange(tcol):
        ti = timestamps[icol]
        for fi in xrange(ifrow):
            if np.isnan(iflaws[fi, ti]):
                tfr[ti, fi] = np.nan
            else:
                tfr[int(np.round(iflaws[fi, ti] * 2 * (n_fbins - 1))), icol] = 1
    freqs = np.arange(n_fbins, dtype=float) / n_fbins * 0.5
    return tfr, timestamps, freqs
Example #3
0
def narrow_band(signal, lag=None, n_fbins=None):
    """Narrow band ambiguity function.

    :param signal: Signal to be analyzed.
    :param lag: vector of lag values.
    :param n_fbins: number of frequency bins
    :type signal: array-like
    :type lag: array-like
    :type n_fbins: int
    :return: Doppler lag representation
    :rtype: array-like
    """

    n = signal.shape[0]
    if lag is None:
        if n % 2 == 0:
            tau_start, tau_end = -n / 2 + 1, n / 2
        else:
            tau_start, tau_end = -(n - 1) / 2, (n + 1) / 2
        lag = np.arange(tau_start, tau_end)
    taucol = lag.shape[0]

    n_fbins = init_default_args(signal, n_fbins=n_fbins)[0]

    naf = np.zeros((n_fbins, taucol), dtype=complex)
    for icol in xrange(taucol):
        taui = lag[icol]
        t = np.arange(abs(taui), n - abs(taui))
        naf[t, icol] = signal[t + taui] * np.conj(signal[t - taui])
    naf = np.fft.fft(naf, axis=0)

    _ix1 = np.arange((n_fbins + (n_fbins % 2)) / 2, n_fbins)
    _ix2 = np.arange((n_fbins + (n_fbins % 2)) / 2)

    _xi1 = -(n_fbins - (n_fbins % 2)) / 2
    _xi2 = ((n_fbins + (n_fbins % 2)) / 2 - 1)
    xi = np.arange(_xi1, _xi2 + 1, dtype=float) / n_fbins
    naf = naf[np.hstack((_ix1, _ix2)), :]
    return naf, lag, xi
Example #4
0
def narrow_band(signal, lag=None, n_fbins=None):
    """Narrow band ambiguity function.

    :param signal: Signal to be analyzed.
    :param lag: vector of lag values.
    :param n_fbins: number of frequency bins
    :type signal: array-like
    :type lag: array-like
    :type n_fbins: int
    :return: Doppler lag representation
    :rtype: array-like
    """

    n = signal.shape[0]
    if lag is None:
        if n % 2 == 0:
            tau_start, tau_end = -n / 2 + 1, n / 2
        else:
            tau_start, tau_end = -(n - 1) / 2, (n + 1) / 2
        lag = np.arange(tau_start, tau_end)
    taucol = lag.shape[0]

    n_fbins = init_default_args(signal, n_fbins=n_fbins)[0]

    naf = np.zeros((n_fbins, taucol), dtype=complex)
    for icol in range(taucol):
        taui = lag[icol]
        t = np.arange(abs(taui), n - abs(taui))
        naf[t, icol] = signal[t + taui] * np.conj(signal[t - taui])
    naf = np.fft.fft(naf, axis=0)

    _ix1 = np.arange((n_fbins + (n_fbins % 2)) / 2, n_fbins)
    _ix2 = np.arange((n_fbins + (n_fbins % 2)) / 2)

    _xi1 = -(n_fbins - (n_fbins % 2)) / 2
    _xi2 = ((n_fbins + (n_fbins % 2)) / 2 - 1)
    xi = np.arange(_xi1, _xi2 + 1, dtype=float) / n_fbins
    naf = naf[np.hstack((_ix1, _ix2)), :]
    return naf, lag, xi
Example #5
0
def smoothed_pseudo_wigner_ville(signal, timestamps=None, freq_bins=None,
                                twindow=None, fwindow=None):
    """Smoothed Pseudo Wigner-Ville time-frequency distribution.
    :param signal: signal to be analyzed
    :param timestamps: time instants of the signal
    :param freq_bins: number of frequency bins
    :param twindow: time smoothing window
    :param fwindow: frequency smoothing window
    :type signal: array-like
    :type timestamps: array-like
    :type freq_bins: int
    :type twindow: array-like
    :type fwindow: array-like
    :return: Smoothed pseudo Wigner Ville distribution
    :rtype: array-like
    """
    timestamps, freq_bins = init_default_args(signal, timestamps=timestamps,
                                              n_fbins=freq_bins)

    if fwindow is None:
        winlength = np.floor(freq_bins / 4.0)
        winlength = winlength + 1 - np.remainder(winlength, 2)
        from scipy.signal import hamming
        fwindow = hamming(int(winlength))
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')

    if twindow is None:
        timelength = np.floor(freq_bins / 10.0)
        timelength += 1 - np.remainder(timelength, 2)
        from scipy.signal import hamming
        twindow = hamming(int(timelength))
    elif twindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')

    tfr = np.zeros((freq_bins, timestamps.shape[0]), dtype=complex)
    lg = (twindow.shape[0] - 1) / 2
    lh = (fwindow.shape[0] - 1) / 2
    for icol in range(timestamps.shape[0]):
        ti = timestamps[icol]
        taumax = min([ti + lg - 1, signal.shape[0] - ti + lg,
                      np.round(freq_bins / 2.0) - 1, lh])
        points = np.arange(-min([lg, signal.shape[0] - ti]),
                           min([lg, ti - 1]) + 1)
        g2 = twindow[lg + points]
        g2 = g2 / np.sum(g2)
        tfr[0, icol] = np.sum(g2 * signal[ti - points - 1] * np.conj(signal[ti - points - 1]))
        for tau in range(int(taumax)):
            points = np.arange(-min([lg, signal.shape[0] - ti - tau]),
                               min([lg, ti - 1 - tau]) + 1)
            g2 = twindow[lg + points]
            g2 = g2 / np.sum(g2)
            R = np.sum(g2 * signal[ti + tau - points - 1] * np.conj(signal[ti - tau - points - 1]))
            tfr[1 + tau, icol] = fwindow[lh + tau + 1] * R
            R = np.sum(g2 * signal[ti - tau - points - 1] * np.conj(signal[ti + tau - points - 1]))
            tfr[freq_bins - tau - 1, icol] = fwindow[lh - tau + 1] * R
        tau = np.round(freq_bins / 2.0)
        if (ti <= signal.shape[0] - tau) and (ti >= tau + 1) and (tau <= lh):
            points = np.arange(-min([lg, signal.shape[0] - ti - tau]),
                               min([lg, ti - 1 - tau]) + 1)
            g2 = twindow[lg + 1 + points]
            g2 = g2 / np.sum(g2)
            _x = np.sum(g2 * signal[ti + tau - points] * np.conj(signal[ti - tau - points]))
            _x *= fwindow[lh + tau + 1]
            _y = np.sum(g2 * signal[ti - tau - points] * np.conj(signal[ti + tau - points]))
            _y *= fwindow[lh - tau + 1]
            tfr[tau, icol] = (_x + _y) * 0.5
    tfr = np.fft.fft(tfr, axis=0)
    return np.real(tfr)
Example #6
0
def smoothed_pseudo_wigner_ville(signal,
                                 timestamps=None,
                                 freq_bins=None,
                                 twindow=None,
                                 fwindow=None):
    """Smoothed Pseudo Wigner-Ville time-frequency distribution.
    :param signal: signal to be analyzed
    :param timestamps: time instants of the signal
    :param freq_bins: number of frequency bins
    :param twindow: time smoothing window
    :param fwindow: frequency smoothing window
    :type signal: array-like
    :type timestamps: array-like
    :type freq_bins: int
    :type twindow: array-like
    :type fwindow: array-like
    :return: Smoothed pseudo Wigner Ville distribution
    :rtype: array-like
    """
    timestamps, freq_bins = init_default_args(signal,
                                              timestamps=timestamps,
                                              n_fbins=freq_bins)

    if fwindow is None:
        winlength = np.floor(freq_bins / 4.0)
        winlength = winlength + 1 - np.remainder(winlength, 2)
        from scipy.signal import hamming
        fwindow = hamming(int(winlength))
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')

    if twindow is None:
        timelength = np.floor(freq_bins / 10.0)
        timelength += 1 - np.remainder(timelength, 2)
        from scipy.signal import hamming
        twindow = hamming(int(timelength))
    elif twindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')

    tfr = np.zeros((freq_bins, timestamps.shape[0]), dtype=complex)
    lg = (twindow.shape[0] - 1) / 2
    lh = (fwindow.shape[0] - 1) / 2
    for icol in xrange(timestamps.shape[0]):
        ti = timestamps[icol]
        taumax = min([
            ti + lg - 1, signal.shape[0] - ti + lg,
            np.round(freq_bins / 2.0) - 1, lh
        ])
        points = np.arange(-min([lg, signal.shape[0] - ti]),
                           min([lg, ti - 1]) + 1)
        g2 = twindow[lg + points]
        g2 = g2 / np.sum(g2)
        tfr[0, icol] = np.sum(g2 * signal[ti - points - 1] *
                              np.conj(signal[ti - points - 1]))
        for tau in xrange(int(taumax)):
            points = np.arange(-min([lg, signal.shape[0] - ti - tau]),
                               min([lg, ti - 1 - tau]) + 1)
            g2 = twindow[lg + points]
            g2 = g2 / np.sum(g2)
            R = np.sum(g2 * signal[ti + tau - points - 1] *
                       np.conj(signal[ti - tau - points - 1]))
            tfr[1 + tau, icol] = fwindow[lh + tau + 1] * R
            R = np.sum(g2 * signal[ti - tau - points - 1] *
                       np.conj(signal[ti + tau - points - 1]))
            tfr[freq_bins - tau - 1, icol] = fwindow[lh - tau + 1] * R
        tau = np.round(freq_bins / 2.0)
        if (ti <= signal.shape[0] - tau) and (ti >= tau + 1) and (tau <= lh):
            points = np.arange(-min([lg, signal.shape[0] - ti - tau]),
                               min([lg, ti - 1 - tau]) + 1)
            g2 = twindow[lg + 1 + points]
            g2 = g2 / np.sum(g2)
            _x = np.sum(g2 * signal[ti + tau - points] *
                        np.conj(signal[ti - tau - points]))
            _x *= fwindow[lh + tau + 1]
            _y = np.sum(g2 * signal[ti - tau - points] *
                        np.conj(signal[ti + tau - points]))
            _y *= fwindow[lh - tau + 1]
            tfr[tau, icol] = (_x + _y) * 0.5
    tfr = np.fft.fft(tfr, axis=0)
    return np.real(tfr)
Example #7
0
def pseudo_margenau_hill(signal, timestamps=None, n_fbins=None, fwindow=None):
    """pseudo_margenau_hill

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param fwindow:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type fwindow:
:return:
:rtype:
    """
    xrow = signal.shape[0]
    timestamps, n_fbins = init_default_args(signal, timestamps=timestamps,
                                            n_fbins=n_fbins)
    tcol = timestamps.shape[0]

    if fwindow is None:
        hlength = np.floor(n_fbins / 4.0)
        if hlength % 2 == 0:
            hlength += 1
        fwindow = ssig.hamming(hlength)
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')
    lh = (fwindow.shape[0] - 1) / 2
    fwindow = fwindow / fwindow[lh]

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    dh = derive_window(fwindow)
    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    for icol in range(tcol):
        ti = timestamps[icol]
        start = min([np.round(n_fbins / 2.0) - 1, lh, xrow - ti])
        end = min([np.round(n_fbins / 2.0) - 1, lh, ti - 1])
        tau = np.arange(-start, end + 1)
        indices = np.remainder(n_fbins + tau, n_fbins)
        tfr[indices, icol] = fwindow[lh + tau] * signal[ti - 1] * np.conj(signal[ti - tau - 1])
        tf2[indices, icol] = dh[lh + tau] * signal[ti - 1] * np.conj(signal[ti - tau - 1])

    tfr = np.fft.fft(tfr, axis=0)
    tf2 = np.fft.fft(tf2, axis=0)
    tfr = tfr.ravel()
    tf2 = tf2.ravel()
    no_warn_mask = tfr != 0
    tf2[no_warn_mask] *= n_fbins / tfr[no_warn_mask] / (2 * np.pi)
    tf2[no_warn_mask] = np.round(tf2[no_warn_mask])
    tfr = np.real(tfr)
    tf2 = np.imag(tf2)
    tfr = tfr.reshape(n_fbins, tcol)
    tf2 = tf2.reshape(n_fbins, tcol)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    threshold = 1.0e-6 * (np.abs(signal) ** 2).mean()

    for icol in range(tcol):
        for jcol in range(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                jcolhat = jcol - tf2[jcol, icol]
                jcolhat = np.remainder(np.remainder(jcolhat - 1,
                                                    n_fbins) + n_fbins, n_fbins)
                jcolhat += 1
                rtfr[jcolhat - 1, icol] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat
            else:
                tf2[jcol, icol] = np.inf
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2
Example #8
0
def spectrogram(signal, time_samples=None, n_fbins=None, window=None):
    """Compute the spectrogram and reassigned spectrogram.

    :param signal: signal to be analzsed
    :param time_samples: time instants (default: np.arange(len(signal)))
    :param n_fbins: number of frequency bins (default: len(signal))
    :param window: frequency smoothing window (default: Hamming with \
        size=len(signal)/4)
    :type signal: array-like
    :type time_samples: array-like
    :type n_fbins: int
    :type window: array-like
    :return: spectrogram, reassigned specstrogram and matrix of reassignment
    vectors
    :rtype: tuple(array-like)
    """

    if time_samples is None:
        time_samples = np.arange(signal.shape[0])
    elif np.unique(np.diff(time_samples)).shape[0] > 1:
        raise ValueError('Time instants must be regularly sampled.')
    n_fbins = init_default_args(signal, n_fbins=n_fbins)[0]
    if window is None:
        wlength = int(np.floor(signal.shape[0] / 4.0))
        wlength += 1 - np.remainder(wlength, 2)
        window = ssig.hamming(wlength)
    elif window.shape[0] % 2 == 0:
        raise ValueError('The smoothing window must have an odd length.')

    tfr = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    tf2 = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    tf3 = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    lh = (window.shape[0] - 1) / 2
    th = window * np.arange(-lh, lh + 1)
    dwin = derive_window(window)

    for icol in range(time_samples.shape[0]):
        ti = time_samples[icol]
        tau = np.arange(-np.min([np.round(n_fbins / 2) - 1, lh, ti]),
                        np.min([np.round(n_fbins / 2) - 1, lh, signal.shape[0] - ti]) + 1)
        indices = np.remainder(n_fbins + tau, n_fbins)
        norm_h = np.linalg.norm(window[lh + tau], ord=2)
        tfr[indices, icol] = signal[ti + tau - 1] * np.conj(window[lh + tau]) / norm_h
        tf2[indices, icol] = signal[ti + tau - 1] * np.conj(th[lh + tau]) / norm_h
        tf3[indices, icol] = signal[ti + tau - 1] * np.conj(dwin[lh + tau]) / norm_h

    tfr = np.fft.fft(tfr, axis=0).ravel()
    tf2 = np.fft.fft(tf2, axis=0).ravel()
    tf3 = np.fft.fft(tf3, axis=0).ravel()

    no_warn_mask = tfr != 0
    tf2[no_warn_mask] = np.round(np.real(tf2[no_warn_mask] / tfr[no_warn_mask]))
    tf3[no_warn_mask] = np.round(np.imag(n_fbins * tf3[no_warn_mask] / tfr[no_warn_mask] / (2 * np.pi)))

    tfr = np.abs(tfr) ** 2
    tfr = tfr.reshape(n_fbins, time_samples.shape[0])
    tf2 = tf2.reshape(n_fbins, time_samples.shape[0])
    tf3 = tf3.reshape(n_fbins, time_samples.shape[0])
    tf3 = np.real(tf3)

    rtfr = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    ix = np.arange(time_samples.min(), time_samples.max() + 1) - 1
    threshold = 1e-6 * np.mean(np.abs(signal[ix])**2)
    for icol in range(time_samples.shape[0]):
        for jcol in range(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                icolhat = icol + tf2[jcol, icol]
                icolhat = np.min([np.max([icolhat, 1]), time_samples.shape[0]])
                jcolhat = jcol - tf3[jcol, icol]
                jcolhat = np.remainder(np.remainder(jcolhat - 1, n_fbins) + n_fbins,
                                       n_fbins)
                rtfr[int(jcolhat), int(icolhat) - 1] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat + 1j * icolhat
            else:
                tf2[jcol, icol] = np.inf
                rtfr[jcol, icol] += tfr[jcol, icol]
    return tfr, rtfr, tf2
Example #9
0
def smoothed_pseudo_wigner_ville(signal, timestamps=None, n_fbins=None,
        twindow=None, fwindow=None):
    """smoothed_pseudo_wigner_ville

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param twindow:
    :param fwindow:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type twindow:
    :type fwindow:
:return:
:rtype:
    """
    xrow = signal.shape[0]

    timestamps, n_fbins = init_default_args(signal, timestamps=timestamps,
                                            n_fbins=n_fbins)
    if fwindow is None:
        hlength = np.floor(n_fbins / 4.0)
        hlength += 1 - (hlength % 2)
        fwindow = ssig.hamming(hlength)
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing window must have an odd length.')
    lh = (fwindow.shape[0] - 1) / 2

    if twindow is None:
        glength = np.floor(n_fbins / 4.0)
        glength += 1 - (glength % 2)
        twindow = ssig.hamming(glength)
    elif twindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing window must have an odd length.')
    lg = (twindow.shape[0] - 1) / 2

    tcol = timestamps.shape[0]
    deltat = timestamps[1:] - timestamps[:-1]
    if deltat.min() != deltat.max():
        raise ValueError("Time instants must be regularly sampled.")
    else:
        dt = deltat.min()

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    tf3 = np.zeros((n_fbins, tcol), dtype=complex)
    dh = derive_window(fwindow)

    for icol in range(tcol):
        ti = timestamps[icol]
        taumax = min([ti + lg - 1, xrow - ti + lg, np.round(n_fbins / 2.0) - 1,
                      lh])
        points = np.arange(-min([lg, xrow - ti]), min([lg, ti - 1]) + 1)
        g2 = twindow[lg + points]
        g2 = g2 / g2.sum()
        tg2 = g2 * points
        xx = signal[ti - 1 - points] * np.conj(signal[ti - 1 - points])
        tfr[0, icol] = (g2 * xx).sum()
        tf2[0, icol] = (tg2 * xx).sum()
        tf3[0, icol] = dh[lh + 1] * tfr[0, icol]

        for tau in range(int(taumax)):
            points = np.arange(-min([lg, xrow - ti - tau]),
                               min([lg, ti - tau - 1]) + 1)
            g2 = twindow[lg + points]
            g2 = g2 / g2.sum()
            tg2 = g2 * points
            xx = signal[ti + tau - 1 - points] * np.conj(signal[ti - tau - 1 - points])
            tfr[tau, icol] = (g2 * xx).sum() * fwindow[lh + tau]
            tf2[tau, icol] = fwindow[lh + tau] * (tg2 * xx).sum()
            tf3[tau, icol] = dh[lh + tau] * (g2 * xx).sum()
            tfr[n_fbins - tau - 1, icol] = (g2 * np.conj(xx)).sum() * fwindow[lh - tau]
            tf2[n_fbins - tau - 1, icol] = (tg2 * np.conj(xx)).sum() * fwindow[lh - tau]
            tf3[n_fbins - tau - 1, icol] = dh[lh - tau] * (g2 * np.conj(xx)).sum()

    tfr = np.real(np.fft.fft(tfr, axis=0)).ravel()
    tf2 = np.real(np.fft.fft(tf2, axis=0)).ravel()
    tf3 = np.imag(np.fft.fft(tf3, axis=0)).ravel()

    no_warn_mask = tfr != 0
    tf2[no_warn_mask] = np.round(tf2[no_warn_mask] / tfr[no_warn_mask] / dt)
    tf3[no_warn_mask] = np.round(n_fbins * tf3[no_warn_mask] /
            tfr[no_warn_mask] / (2 * np.pi))
    tfr, tf2, tf3 = [x.reshape(n_fbins, tcol).astype(complex) for x in (tfr, tf2, tf3)]
    tf3 = np.real(tf3)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    ex = np.mean(np.abs(signal) ** 2)
    threshold = ex * 1.0e-6

    for icol in range(tcol):
        for jcol in range(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                icolhat = min(max([icol - tf2[jcol, icol], 1]), tcol)
                jcolhat = jcol - tf3[jcol, icol]
                jcolhat = (((int(jcolhat) - 1) % n_fbins) + n_fbins) % n_fbins + 1
                rtfr[jcol, icol] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat + 1j * icolhat
            else:
                tf2[jcol, icol] = np.inf * (1 + 1j)
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2
Example #10
0
def morlet_scalogram(signal, timestamps=None, n_fbins=None, tbp=0.25):
    """morlet_scalogram

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param tbp:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type tbp:
:return:
:rtype:
    """
    xrow = signal.shape[0]
    timestamps, n_fbins = init_default_args(signal, timestamps=timestamps,
                                            n_fbins=n_fbins)
    k = 0.001
    tcol = timestamps.shape[0]
    deltat = timestamps[1:] - timestamps[:-1]
    if deltat.min() != deltat.max():
        raise ValueError("Time instants must be regularly sampled.")
    else:
        dt = deltat.min()

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    M = np.ceil(tbp * n_fbins * np.sqrt(2 * np.log(1 / k)))
    tau = np.arange(M + int(np.round(n_fbins / 2)) + 1)
    hstar = np.exp(-(tau / (n_fbins * tbp)) ** 2 / 2.0) * np.exp(-1j * 2 *
            np.pi * tau / n_fbins)
    thstar = tau * hstar

    for m in range(1, int(np.round(n_fbins / 2))):
        factor = np.sqrt(m / (tbp * n_fbins))
        for icol in range(tcol):
            ti = timestamps[icol]
            tau_neg = np.arange(1, min([np.ceil(M / m), ti - 1]) + 1).astype(int)
            tau_pos = np.arange(min([np.ceil(M / m), xrow - ti]) + 1).astype(int)
            # positive frequencies
            tfr[m, icol] = np.dot(hstar[m * tau_pos - 1],
                                  signal[ti + tau_pos - 1])
            tf2[m, icol] = np.dot(thstar[m * tau_pos - 1],
                                  signal[ti + tau_pos - 1])
            if tau_neg.shape[0] > 0:
                tfr[m, icol] += np.dot(np.conj(hstar[tau_neg * m]),
                                       signal[ti - tau_neg])
                tf2[m, icol] -= np.dot(np.conj(thstar[tau_neg * m]),
                                       signal[ti - tau_neg])
            # negative frequencies
            tfr[n_fbins - m, icol] = np.dot(np.conj(hstar[tau_pos * m - 1]),
                                            signal[ti + tau_pos - 1])
            tf2[n_fbins - m, icol] = np.dot(np.conj(thstar[tau_pos * m - 1]),
                                            signal[ti + tau_pos - 1])
            if tau_neg.shape[0] > 0:
                tfr[n_fbins - m, icol] += np.dot(hstar[tau_neg * m],
                                                 signal[ti - tau_neg])
                tf2[n_fbins - m, icol] -= np.dot(thstar[tau_neg * m],
                                                 signal[ti - tau_neg])
        tfr[m, :] *= factor
        tf2[m, :] *= factor / m
        tfr[n_fbins - m, :] *= factor
        tf2[n_fbins - m, :] *= factor / m

    m = int(np.round(n_fbins / 2.0))
    factor = np.sqrt(m / (tbp * n_fbins))
    for icol in range(tcol):
        ti = timestamps[icol]
        tau_neg = np.arange(1, min([np.ceil(M / m), ti - 1]) + 1).astype(int)
        tau_pos = np.arange(min([np.ceil(M / m), xrow - ti]) + 1).astype(int)
        tau_pos -= 1
        tau_neg -= 1

        tfr[m, icol] = np.dot(hstar[m * tau_pos], signal[ti + tau_pos])
        tf2[m, icol] = np.dot(thstar[m * tau_pos], signal[ti + tau_pos])
        if tau_neg.shape[0] > 0:
            tfr[m, icol] += np.dot(np.conj(hstar[tau_neg * m]),
                                   signal[ti - tau_neg])
            tf2[m, icol] -= np.dot(np.conj(thstar[tau_neg * m]),
                                   signal[ti - tau_neg])
    tfr[m, :] *= factor
    tf2[m, :] *= factor / m

    tfr, tf2 = tfr.ravel(), tf2.ravel()
    no_warn_mask = tfr != 0
    tf2[no_warn_mask] = tf2[no_warn_mask] / tfr[no_warn_mask]
    tfr = np.abs(tfr) ** 2
    tfr = tfr.reshape(n_fbins, tcol)
    tf2 = tf2.reshape(n_fbins, tcol).astype(complex)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    ex = np.mean(np.abs(signal) ** 2)
    threshold = ex * 1.0e-6
    factor = 2 * np.pi * n_fbins * (tbp ** 2)
    for icol in range(tcol):
        for jcol in range(n_fbins):
            if tfr[jcol, icol] > threshold:
                icolhat = icol + np.round(np.real(tf2[jcol, icol] / dt))
                icolhat = min([max([icolhat, 1]), tcol])
                m = np.remainder(jcol + np.round(n_fbins / 2.0) - 2,
                                 n_fbins)
                m -= np.round(n_fbins / 2.0) + 1
                jcolhat = jcol + np.round(np.imag((m ** 2) * tf2[jcol, icol] / factor))
                jcolhat = np.remainder(
                        np.remainder(jcolhat - 1, n_fbins) + n_fbins,
                        n_fbins) + 1
                rtfr[jcolhat - 1, icolhat - 1] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat + 1j * icolhat
            else:
                tf2[jcol, icol] = np.inf * (1 + 1j)
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2
Example #11
0
def pseudo_wigner_ville(signal, timestamps=None, n_fbins=None, fwindow=None):
    """pseudo_wigner_ville

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param fwindow:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type fwindow:
:return:
:rtype:
    """
    xrow = signal.shape[0]
    timestamps, n_fbins = init_default_args(signal, timestamps=timestamps,
                                            n_fbins=n_fbins)
    tcol = timestamps.shape[0]

    if fwindow is None:
        hlength = np.floor(n_fbins / 4.0)
        if hlength % 2 == 0:
            hlength += 1
        fwindow = ssig.hamming(hlength)
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')
    lh = (fwindow.shape[0] - 1) / 2
    fwindow = fwindow / fwindow[lh]

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    dh = derive_window(fwindow)
    for icol in range(tcol):
        ti = timestamps[icol]
        taumax = min([ti - 1, xrow - ti, np.round(n_fbins / 2.0) - 1, lh])
        tau = np.arange(-taumax, taumax + 1)
        indices = np.remainder(n_fbins + tau, n_fbins) + 1
        tfr[indices - 1, icol] = fwindow[lh + tau] * signal[ti + tau - 1] * np.conj(signal[ti - tau - 1])
        tf2[indices - 1, icol] = dh[lh + tau] * signal[ti + tau - 1] * np.conj(signal[ti - tau - 1])
        tau = np.round(n_fbins / 2)
        if (ti <= (xrow - tau)) and (ti > (tau + 1)) and (tau <= lh):
            _x = fwindow[lh + 1 + tau] * signal[ti + tau] * np.conj(signal[ti - tau])
            _y = fwindow[lh + 1 - tau] * signal[ti - tau] * np.conj(signal[ti + tau])
            tfr[tau + 1, icol] = (_x + _y) * 0.5
            _x = dh[lh + 1 + tau] * signal[ti + tau] * np.conj(signal[ti - tau])
            _y = dh[lh + 1 - tau] * signal[ti - tau] * np.conj(signal[ti + tau])
            tf2[tau + 1, icol] = (_x + _y) * 0.5
    tfr = np.real(np.fft.fft(tfr, axis=0))
    tf2 = np.imag(np.fft.fft(tf2, axis=0))
    tfr = tfr.ravel()
    tf2 = tf2.ravel()
    no_warn_mask = tfr != 0
    tf2[no_warn_mask] *= n_fbins / tfr[no_warn_mask] / (2 * np.pi)
    tf2[no_warn_mask] = np.round(tf2[no_warn_mask])
    tfr = tfr.reshape(n_fbins, tcol)
    tf2 = tf2.reshape(n_fbins, tcol)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    tmin = timestamps.min()
    tmax = timestamps.max()
    threshold = 1.0e-6 * (np.abs(signal[tmin:(tmax + 1)]) ** 2).mean()

    for icol in range(tcol):
        for jcol in range(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                jcolhat = jcol - tf2[jcol, icol]
                jcolhat = np.remainder(np.remainder(jcolhat - 1,
                                                    n_fbins) + n_fbins, n_fbins)
                jcolhat += 1
                rtfr[jcolhat - 1, icol] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat
            else:
                tf2[jcol, icol] = np.inf
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2
Example #12
0
def spectrogram(signal, time_samples=None, n_fbins=None, window=None):
    """Compute the spectrogram and reassigned spectrogram.

    :param signal: signal to be analzsed
    :param time_samples: time instants (default: np.arange(len(signal)))
    :param n_fbins: number of frequency bins (default: len(signal))
    :param window: frequency smoothing window (default: Hamming with \
        size=len(signal)/4)
    :type signal: array-like
    :type time_samples: array-like
    :type n_fbins: int
    :type window: array-like
    :return: spectrogram, reassigned specstrogram and matrix of reassignment
    vectors
    :rtype: tuple(array-like)
    """

    if time_samples is None:
        time_samples = np.arange(signal.shape[0])
    elif np.unique(np.diff(time_samples)).shape[0] > 1:
        raise ValueError('Time instants must be regularly sampled.')
    n_fbins = init_default_args(signal, n_fbins=n_fbins)[0]
    if window is None:
        wlength = int(np.floor(signal.shape[0] / 4.0))
        wlength += 1 - np.remainder(wlength, 2)
        window = ssig.hamming(wlength)
    elif window.shape[0] % 2 == 0:
        raise ValueError('The smoothing window must have an odd length.')

    tfr = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    tf2 = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    tf3 = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    lh = (window.shape[0] - 1) / 2
    th = window * np.arange(-lh, lh + 1)
    dwin = derive_window(window)

    for icol in xrange(time_samples.shape[0]):
        ti = time_samples[icol]
        tau = np.arange(
            -np.min([np.round(n_fbins / 2) - 1, lh, ti]),
            np.min([np.round(n_fbins / 2) - 1, lh, signal.shape[0] - ti]) + 1)
        indices = np.remainder(n_fbins + tau, n_fbins)
        norm_h = np.linalg.norm(window[lh + tau], ord=2)
        tfr[indices,
            icol] = signal[ti + tau - 1] * np.conj(window[lh + tau]) / norm_h
        tf2[indices,
            icol] = signal[ti + tau - 1] * np.conj(th[lh + tau]) / norm_h
        tf3[indices,
            icol] = signal[ti + tau - 1] * np.conj(dwin[lh + tau]) / norm_h

    tfr = np.fft.fft(tfr, axis=0).ravel()
    tf2 = np.fft.fft(tf2, axis=0).ravel()
    tf3 = np.fft.fft(tf3, axis=0).ravel()

    no_warn_mask = tfr != 0
    tf2[no_warn_mask] = np.round(np.real(tf2[no_warn_mask] /
                                         tfr[no_warn_mask]))
    tf3[no_warn_mask] = np.round(
        np.imag(n_fbins * tf3[no_warn_mask] / tfr[no_warn_mask] / (2 * np.pi)))

    tfr = np.abs(tfr)**2
    tfr = tfr.reshape(n_fbins, time_samples.shape[0])
    tf2 = tf2.reshape(n_fbins, time_samples.shape[0])
    tf3 = tf3.reshape(n_fbins, time_samples.shape[0])
    tf3 = np.real(tf3)

    rtfr = np.zeros((n_fbins, time_samples.shape[0]), dtype=complex)
    ix = np.arange(time_samples.min(), time_samples.max() + 1) - 1
    threshold = 1e-6 * np.mean(np.abs(signal[ix])**2)
    for icol in xrange(time_samples.shape[0]):
        for jcol in xrange(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                icolhat = icol + tf2[jcol, icol]
                icolhat = np.min([np.max([icolhat, 1]), time_samples.shape[0]])
                jcolhat = jcol - tf3[jcol, icol]
                jcolhat = np.remainder(
                    np.remainder(jcolhat - 1, n_fbins) + n_fbins, n_fbins)
                rtfr[int(jcolhat), int(icolhat) - 1] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat + 1j * icolhat
            else:
                tf2[jcol, icol] = np.inf
                rtfr[jcol, icol] += tfr[jcol, icol]
    return tfr, rtfr, tf2
Example #13
0
def smoothed_pseudo_wigner_ville(signal,
                                 timestamps=None,
                                 n_fbins=None,
                                 twindow=None,
                                 fwindow=None):
    """smoothed_pseudo_wigner_ville

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param twindow:
    :param fwindow:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type twindow:
    :type fwindow:
:return:
:rtype:
    """
    xrow = signal.shape[0]

    timestamps, n_fbins = init_default_args(signal,
                                            timestamps=timestamps,
                                            n_fbins=n_fbins)
    if fwindow is None:
        hlength = np.floor(n_fbins / 4.0)
        hlength += 1 - (hlength % 2)
        fwindow = ssig.hamming(hlength)
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing window must have an odd length.')
    lh = (fwindow.shape[0] - 1) / 2

    if twindow is None:
        glength = np.floor(n_fbins / 4.0)
        glength += 1 - (glength % 2)
        twindow = ssig.hamming(glength)
    elif twindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing window must have an odd length.')
    lg = (twindow.shape[0] - 1) / 2

    tcol = timestamps.shape[0]
    deltat = timestamps[1:] - timestamps[:-1]
    if deltat.min() != deltat.max():
        raise ValueError("Time instants must be regularly sampled.")
    else:
        dt = deltat.min()

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    tf3 = np.zeros((n_fbins, tcol), dtype=complex)
    dh = derive_window(fwindow)

    for icol in xrange(tcol):
        ti = timestamps[icol]
        taumax = min(
            [ti + lg - 1, xrow - ti + lg,
             np.round(n_fbins / 2.0) - 1, lh])
        points = np.arange(-min([lg, xrow - ti]), min([lg, ti - 1]) + 1)
        g2 = twindow[lg + points]
        g2 = g2 / g2.sum()
        tg2 = g2 * points
        xx = signal[ti - 1 - points] * np.conj(signal[ti - 1 - points])
        tfr[0, icol] = (g2 * xx).sum()
        tf2[0, icol] = (tg2 * xx).sum()
        tf3[0, icol] = dh[lh + 1] * tfr[0, icol]

        for tau in xrange(int(taumax)):
            points = np.arange(-min([lg, xrow - ti - tau]),
                               min([lg, ti - tau - 1]) + 1)
            g2 = twindow[lg + points]
            g2 = g2 / g2.sum()
            tg2 = g2 * points
            xx = signal[ti + tau - 1 - points] * np.conj(
                signal[ti - tau - 1 - points])
            tfr[tau, icol] = (g2 * xx).sum() * fwindow[lh + tau]
            tf2[tau, icol] = fwindow[lh + tau] * (tg2 * xx).sum()
            tf3[tau, icol] = dh[lh + tau] * (g2 * xx).sum()
            tfr[n_fbins - tau - 1,
                icol] = (g2 * np.conj(xx)).sum() * fwindow[lh - tau]
            tf2[n_fbins - tau - 1,
                icol] = (tg2 * np.conj(xx)).sum() * fwindow[lh - tau]
            tf3[n_fbins - tau - 1,
                icol] = dh[lh - tau] * (g2 * np.conj(xx)).sum()

    tfr = np.real(np.fft.fft(tfr, axis=0)).ravel()
    tf2 = np.real(np.fft.fft(tf2, axis=0)).ravel()
    tf3 = np.imag(np.fft.fft(tf3, axis=0)).ravel()

    no_warn_mask = tfr != 0
    tf2[no_warn_mask] = np.round(tf2[no_warn_mask] / tfr[no_warn_mask] / dt)
    tf3[no_warn_mask] = np.round(n_fbins * tf3[no_warn_mask] /
                                 tfr[no_warn_mask] / (2 * np.pi))
    tfr, tf2, tf3 = [
        x.reshape(n_fbins, tcol).astype(complex) for x in (tfr, tf2, tf3)
    ]
    tf3 = np.real(tf3)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    ex = np.mean(np.abs(signal)**2)
    threshold = ex * 1.0e-6

    for icol in xrange(tcol):
        for jcol in xrange(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                icolhat = min(max([icol - tf2[jcol, icol], 1]), tcol)
                jcolhat = jcol - tf3[jcol, icol]
                jcolhat = ((
                    (int(jcolhat) - 1) % n_fbins) + n_fbins) % n_fbins + 1
                rtfr[jcol, icol] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat + 1j * icolhat
            else:
                tf2[jcol, icol] = np.inf * (1 + 1j)
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2
Example #14
0
def morlet_scalogram(signal, timestamps=None, n_fbins=None, tbp=0.25):
    """morlet_scalogram

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param tbp:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type tbp:
:return:
:rtype:
    """
    xrow = signal.shape[0]
    timestamps, n_fbins = init_default_args(signal,
                                            timestamps=timestamps,
                                            n_fbins=n_fbins)
    k = 0.001
    tcol = timestamps.shape[0]
    deltat = timestamps[1:] - timestamps[:-1]
    if deltat.min() != deltat.max():
        raise ValueError("Time instants must be regularly sampled.")
    else:
        dt = deltat.min()

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    M = np.ceil(tbp * n_fbins * np.sqrt(2 * np.log(1 / k)))
    tau = np.arange(M + int(np.round(n_fbins / 2)) + 1)
    hstar = np.exp(-(tau / (n_fbins * tbp))**2 / 2.0) * np.exp(
        -1j * 2 * np.pi * tau / n_fbins)
    thstar = tau * hstar

    for m in xrange(1, int(np.round(n_fbins / 2))):
        factor = np.sqrt(m / (tbp * n_fbins))
        for icol in xrange(tcol):
            ti = timestamps[icol]
            tau_neg = np.arange(1,
                                min([np.ceil(M / m), ti - 1]) + 1).astype(int)
            tau_pos = np.arange(min([np.ceil(M / m), xrow - ti]) +
                                1).astype(int)
            # positive frequencies
            tfr[m, icol] = np.dot(hstar[m * tau_pos - 1],
                                  signal[ti + tau_pos - 1])
            tf2[m, icol] = np.dot(thstar[m * tau_pos - 1],
                                  signal[ti + tau_pos - 1])
            if tau_neg.shape[0] > 0:
                tfr[m, icol] += np.dot(np.conj(hstar[tau_neg * m]),
                                       signal[ti - tau_neg])
                tf2[m, icol] -= np.dot(np.conj(thstar[tau_neg * m]),
                                       signal[ti - tau_neg])
            # negative frequencies
            tfr[n_fbins - m, icol] = np.dot(np.conj(hstar[tau_pos * m - 1]),
                                            signal[ti + tau_pos - 1])
            tf2[n_fbins - m, icol] = np.dot(np.conj(thstar[tau_pos * m - 1]),
                                            signal[ti + tau_pos - 1])
            if tau_neg.shape[0] > 0:
                tfr[n_fbins - m, icol] += np.dot(hstar[tau_neg * m],
                                                 signal[ti - tau_neg])
                tf2[n_fbins - m, icol] -= np.dot(thstar[tau_neg * m],
                                                 signal[ti - tau_neg])
        tfr[m, :] *= factor
        tf2[m, :] *= factor / m
        tfr[n_fbins - m, :] *= factor
        tf2[n_fbins - m, :] *= factor / m

    m = int(np.round(n_fbins / 2.0))
    factor = np.sqrt(m / (tbp * n_fbins))
    for icol in xrange(tcol):
        ti = timestamps[icol]
        tau_neg = np.arange(1, min([np.ceil(M / m), ti - 1]) + 1).astype(int)
        tau_pos = np.arange(min([np.ceil(M / m), xrow - ti]) + 1).astype(int)
        tau_pos -= 1
        tau_neg -= 1

        tfr[m, icol] = np.dot(hstar[m * tau_pos], signal[ti + tau_pos])
        tf2[m, icol] = np.dot(thstar[m * tau_pos], signal[ti + tau_pos])
        if tau_neg.shape[0] > 0:
            tfr[m, icol] += np.dot(np.conj(hstar[tau_neg * m]),
                                   signal[ti - tau_neg])
            tf2[m, icol] -= np.dot(np.conj(thstar[tau_neg * m]),
                                   signal[ti - tau_neg])
    tfr[m, :] *= factor
    tf2[m, :] *= factor / m

    tfr, tf2 = tfr.ravel(), tf2.ravel()
    no_warn_mask = tfr != 0
    tf2[no_warn_mask] = tf2[no_warn_mask] / tfr[no_warn_mask]
    tfr = np.abs(tfr)**2
    tfr = tfr.reshape(n_fbins, tcol)
    tf2 = tf2.reshape(n_fbins, tcol).astype(complex)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    ex = np.mean(np.abs(signal)**2)
    threshold = ex * 1.0e-6
    factor = 2 * np.pi * n_fbins * (tbp**2)
    for icol in xrange(tcol):
        for jcol in xrange(n_fbins):
            if tfr[jcol, icol] > threshold:
                icolhat = icol + np.round(np.real(tf2[jcol, icol] / dt))
                icolhat = min([max([icolhat, 1]), tcol])
                m = np.remainder(jcol + np.round(n_fbins / 2.0) - 2, n_fbins)
                m -= np.round(n_fbins / 2.0) + 1
                jcolhat = jcol + np.round(
                    np.imag((m**2) * tf2[jcol, icol] / factor))
                jcolhat = np.remainder(
                    np.remainder(jcolhat - 1, n_fbins) + n_fbins, n_fbins) + 1
                rtfr[jcolhat - 1, icolhat - 1] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat + 1j * icolhat
            else:
                tf2[jcol, icol] = np.inf * (1 + 1j)
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2
Example #15
0
def pseudo_page(signal, timestamps=None, n_fbins=None, fwindow=None):
    """pseudo_page

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param fwindow:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type fwindow:
:return:
:rtype:
    """
    timestamps, n_fbins = init_default_args(signal,
                                            timestamps=timestamps,
                                            n_fbins=n_fbins)
    tcol = timestamps.shape[0]

    if fwindow is None:
        hlength = np.floor(n_fbins / 4.0)
        if hlength % 2 == 0:
            hlength += 1
        fwindow = ssig.hamming(hlength)
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')
    lh = (fwindow.shape[0] - 1) / 2
    fwindow = fwindow / fwindow[lh]

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    dh = derive_window(fwindow)

    for icol in xrange(tcol):
        tau = np.arange(min([n_fbins - 1, lh, icol - 1]) + 1)
        indices = np.remainder(n_fbins + tau, n_fbins) + 1
        tfr[indices, icol] = fwindow[lh + tau] * signal[icol] * np.conj(
            signal[icol - tau])
        tf2[indices,
            icol] = dh[lh + tau] * signal[icol] * np.conj(signal[icol - tau])
        tf2[0, icol] += signal[icol] * np.conj(signal[icol])

    tfr = np.fft.fft(tfr, axis=0)
    tf2 = np.fft.fft(tf2, axis=0)
    tfr = tfr.ravel()
    tf2 = tf2.ravel()
    no_warn_mask = tfr != 0
    tf2[no_warn_mask] *= n_fbins / tfr[no_warn_mask] / (2 * np.pi)
    tf2[no_warn_mask] = np.round(tf2[no_warn_mask])
    tfr = np.real(tfr)
    tf2 = np.imag(tf2)
    tfr = tfr.reshape(n_fbins, tcol)
    tf2 = tf2.reshape(n_fbins, tcol)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    threshold = 1.0e-6 * (np.abs(signal)**2).mean()

    for icol in xrange(tcol):
        for jcol in xrange(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                jcolhat = jcol - tf2[jcol, icol]
                jcolhat = np.remainder(
                    np.remainder(jcolhat - 1, n_fbins) + n_fbins, n_fbins)
                jcolhat += 1
                rtfr[jcolhat - 1, icol] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat
            else:
                tf2[jcol, icol] = np.inf
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2
Example #16
0
def pseudo_wigner_ville(signal, timestamps=None, n_fbins=None, fwindow=None):
    """pseudo_wigner_ville

    :param signal:
    :param timestamps:
    :param n_fbins:
    :param fwindow:
    :type signal:
    :type timestamps:
    :type n_fbins:
    :type fwindow:
:return:
:rtype:
    """
    xrow = signal.shape[0]
    timestamps, n_fbins = init_default_args(signal,
                                            timestamps=timestamps,
                                            n_fbins=n_fbins)
    tcol = timestamps.shape[0]

    if fwindow is None:
        hlength = np.floor(n_fbins / 4.0)
        if hlength % 2 == 0:
            hlength += 1
        fwindow = ssig.hamming(hlength)
    elif fwindow.shape[0] % 2 == 0:
        raise ValueError('The smoothing fwindow must have an odd length.')
    lh = (fwindow.shape[0] - 1) / 2
    fwindow = fwindow / fwindow[lh]

    tfr = np.zeros((n_fbins, tcol), dtype=complex)
    tf2 = np.zeros((n_fbins, tcol), dtype=complex)
    dh = derive_window(fwindow)
    for icol in xrange(tcol):
        ti = timestamps[icol]
        taumax = min([ti - 1, xrow - ti, np.round(n_fbins / 2.0) - 1, lh])
        tau = np.arange(-taumax, taumax + 1)
        indices = np.remainder(n_fbins + tau, n_fbins) + 1
        tfr[indices - 1,
            icol] = fwindow[lh + tau] * signal[ti + tau - 1] * np.conj(
                signal[ti - tau - 1])
        tf2[indices - 1, icol] = dh[lh + tau] * signal[ti + tau - 1] * np.conj(
            signal[ti - tau - 1])
        tau = np.round(n_fbins / 2)
        if (ti <= (xrow - tau)) and (ti > (tau + 1)) and (tau <= lh):
            _x = fwindow[lh + 1 + tau] * signal[ti + tau] * np.conj(
                signal[ti - tau])
            _y = fwindow[lh + 1 - tau] * signal[ti - tau] * np.conj(
                signal[ti + tau])
            tfr[tau + 1, icol] = (_x + _y) * 0.5
            _x = dh[lh + 1 + tau] * signal[ti + tau] * np.conj(
                signal[ti - tau])
            _y = dh[lh + 1 - tau] * signal[ti - tau] * np.conj(
                signal[ti + tau])
            tf2[tau + 1, icol] = (_x + _y) * 0.5
    tfr = np.real(np.fft.fft(tfr, axis=0))
    tf2 = np.imag(np.fft.fft(tf2, axis=0))
    tfr = tfr.ravel()
    tf2 = tf2.ravel()
    no_warn_mask = tfr != 0
    tf2[no_warn_mask] *= n_fbins / tfr[no_warn_mask] / (2 * np.pi)
    tf2[no_warn_mask] = np.round(tf2[no_warn_mask])
    tfr = tfr.reshape(n_fbins, tcol)
    tf2 = tf2.reshape(n_fbins, tcol)

    rtfr = np.zeros((n_fbins, tcol), dtype=complex)
    tmin = timestamps.min()
    tmax = timestamps.max()
    threshold = 1.0e-6 * (np.abs(signal[tmin:(tmax + 1)])**2).mean()

    for icol in xrange(tcol):
        for jcol in xrange(n_fbins):
            if np.abs(tfr[jcol, icol]) > threshold:
                jcolhat = jcol - tf2[jcol, icol]
                jcolhat = np.remainder(
                    np.remainder(jcolhat - 1, n_fbins) + n_fbins, n_fbins)
                jcolhat += 1
                rtfr[jcolhat - 1, icol] += tfr[jcol, icol]
                tf2[jcol, icol] = jcolhat
            else:
                tf2[jcol, icol] = np.inf
                rtfr[jcol, icol] += tfr[jcol, icol]

    return tfr, rtfr, tf2