Exemplo n.º 1
0
def mkl_toeplitz_multiplication(c, r, A, A_padded=False, out=None, fft_len=None):
    """
    Compute numpy.dot(scipy.linalg.toeplitz(c,r), A) using the FFT from the mkl_fft package.

    Parameters
    ----------
    c: ndarray
        the first column of the Toeplitz matrix
    r: ndarray
        the first row of the Toeplitz matrix
    A: ndarray
        the matrix to multiply on the right
    A_padded: bool, optional
        the A matrix can be pre-padded with zeros by the user, if this is the case
        set to True
    out: ndarray, optional
        an ndarray to store the output of the multiplication
    fft_len: int, optional
        specify the length of the FFT to use
    """

    if not has_mklfft:
        raise ValueError(
            "Import mkl_fft package unavailable. Install from https://github.com/LCAV/mkl_fft"
        )

    m = c.shape[0]
    n = r.shape[0]

    if fft_len is None:
        fft_len = int(2 ** np.ceil(np.log2(m + n - 1)))
    zp = fft_len - m - n + 1

    if (not A_padded and A.shape[0] != n) or (A_padded and A.shape[0] != fft_len):
        raise ValueError("A dimensions not compatible with toeplitz(c,r)")

    x = np.concatenate((c, np.zeros(zp, dtype=c.dtype), r[-1:0:-1]))
    xf = fft.rfft(x, n=fft_len)

    if out is not None:
        fft.rfft(A, n=fft_len, axis=0, out=out)
    else:
        out = fft.rfft(A, n=fft_len, axis=0)

    out *= xf[:, None]

    if A_padded:
        fft.irfft(out, n=fft_len, axis=0, out=A)
    else:
        A = fft.irfft(out, n=fft_len, axis=0)

    return A[
        :m,
    ]
Exemplo n.º 2
0
    def test_rfft(self):
        n_tests = 1000
        n_max = 2
        d_max = 100

        norm = 'ortho'
        inplace = True
        scrambled = True
        dtype = np.float64

        passed = True

        for i in range(n_tests):
            ndim = np.random.randint(1,high=n_max+1)
            axis = np.random.randint(0,high=ndim)
            dims = np.random.randint(1,high=d_max+1,size=(ndim))

            x = np.array(np.random.normal(size=dims), dtype=dtype)
            x = np.asfortranarray(x)

            X = rfft(x, axis=axis, norm=norm, scrambled=scrambled)

            Y = np.fft.rfft(x, axis=axis, norm=norm)

            x_ = irfft(X, n=x.shape[axis], axis=axis, norm=norm, scrambled=scrambled)

            if not np.allclose(X,Y):
                print('  Failed forward with ndim=%d axis=%d dims=' % (ndim, axis), dims)
                passed = False

            if not np.allclose(x, x_):
                print('  Failed backward with ndim=%d axis=%d dims=' % (ndim, axis), dims)
                passed = False

        self.assertTrue(passed)
Exemplo n.º 3
0
def autocorr(x):
    """Fast autocorrelation computation using the FFT"""

    X = fft.rfft(x, n=2 * x.shape[0])
    r = fft.irfft(np.abs(X) ** 2)

    return r[: x.shape[0]] / (x.shape[0] - 1)
Exemplo n.º 4
0
 def test5(self):
     for a in range(0,3):
         for ovwr_x in [True, False]:
             for dt, atol in zip([np.float32, np.float64], [4e-7, 4e-15]):
                 x = self.t3.copy().astype(dt)
                 f1 = mkl_fft.irfft(x, axis=a, overwrite_x=ovwr_x)
                 f2 = mkl_fft.rfft(f1, axis=a, overwrite_x=ovwr_x)
                 assert_allclose(f2, self.t3.astype(dt), atol=atol)
Exemplo n.º 5
0
 def test3(self):
     for a in range(0,2):
         for ovwr_x in [True, False]:
             for dt, atol in zip([np.float32, np.float64], [2e-7, 2e-15]):
                 x = self.m2.copy().astype(dt)
                 f1 = mkl_fft.rfft(x, axis=a, overwrite_x=ovwr_x)
                 f2 = mkl_fft.irfft(f1, axis=a, overwrite_x=ovwr_x)
                 assert_allclose(f2, self.m2.astype(dt), atol=atol, err_msg=(a, ovwr_x))
Exemplo n.º 6
0
def deconvolve(y, s, length=None, thresh=0.0):
    '''
    Deconvolve an excitation signal from an impulse response

    Parameters
    ----------

    y : ndarray
        The recording
    s : ndarray
        The excitation signal
    length: int, optional
        the length of the impulse response to deconvolve
    thresh : float, optional
        ignore frequency bins with power lower than this
    '''

    # FFT length including zero padding
    n = y.shape[0] + s.shape[0] - 1

    # let FFT size be even for convenience
    if n % 2 != 0:
        n += 1

    # when unknown, pick the filter size as size of test signal
    if length is None:
        length = n

    # Forward transforms
    Y = fft.rfft(np.array(y, dtype=np.float32), n=n) / np.sqrt(n)
    S = fft.rfft(np.array(s, dtype=np.float32), n=n) / np.sqrt(n)

    # Only do the division where S is large enough
    H = np.zeros(*Y.shape, dtype=Y.dtype)
    I = np.where(np.abs(S) > thresh)
    H[I] = Y[I] / S[I]

    # Inverse transform
    h = fft.irfft(H, n=n)

    return h[:length]
Exemplo n.º 7
0
    def test_scale_1d_array(self):
        X = np.ones((8, 4, 4,), dtype='d')
        f1 = mkl_fft.fft(X, axis=1, forward_scale=0.25)
        f2 = mkl_fft.fft(X, axis=1)
        r_tol, a_tol = _get_rtol_atol(X)
        assert_allclose(4*f1, f2, rtol=r_tol, atol=a_tol)

        X1 = mkl_fft.ifft(f1, axis=1, forward_scale=0.25)
        assert_allclose(X, X1, rtol=r_tol, atol=a_tol)

        f3 = mkl_fft.rfft(X, axis=0, forward_scale=0.5)
        X2 = mkl_fft.irfft(f3, axis=0, forward_scale=0.5)
        assert_allclose(X, X2, rtol=r_tol, atol=a_tol)
Exemplo n.º 8
0
    def test_scale_1d_vector(self):
        X = np.ones(128, dtype='d')
        f1 = mkl_fft.fft(X, forward_scale=0.25)
        f2 = mkl_fft.fft(X)
        r_tol, a_tol = _get_rtol_atol(X)
        assert_allclose(4*f1, f2, rtol=r_tol, atol=a_tol)

        X1 = mkl_fft.ifft(f1, forward_scale=0.25)
        assert_allclose(X, X1, rtol=r_tol, atol=a_tol)

        f3 = mkl_fft.rfft(X, forward_scale=0.5)
        X2 = mkl_fft.irfft(f3, forward_scale=0.5)
        assert_allclose(X, X2, rtol=r_tol, atol=a_tol)
Exemplo n.º 9
0
def correlate(x1, x2, interp=1, phat=False):
    '''
    Compute the cross-correlation between x1 and x2

    Parameters
    ----------
    x1,x2: array_like
        The data arrays
    interp: int, optional
        The interpolation factor for the output array, default 1.
    phat: bool, optional
        Apply the PHAT weighting (default False)

    Returns
    -------
    The cross-correlation between the two arrays
    '''

    N1 = x1.shape[0]
    N2 = x2.shape[0]

    N = N1 + N2 - 1

    X1 = fft.rfft(x1, n=N)
    X2 = fft.rfft(x2, n=N)

    if phat:
        eps1 = np.mean(np.abs(X1)) * 1e-10
        X1 /= (np.abs(X1) + eps1)
        eps2 = np.mean(np.abs(X2)) * 1e-10
        X2 /= (np.abs(X2) + eps2)

    m = np.minimum(N1, N2)

    out = fft.irfft(X1 * np.conj(X2), n=int(N * interp))

    return np.concatenate([out[-interp * (N2 - 1):], out[:(interp * N1)]])
Exemplo n.º 10
0
    def test_rfft(self):
        n_tests = 1000
        n_max = 2
        d_max = 100

        norm = 'ortho'
        inplace = True
        scrambled = True
        dtype = np.float64

        passed = True

        for i in range(n_tests):
            ndim = np.random.randint(1, high=n_max + 1)
            axis = np.random.randint(0, high=ndim)
            dims = np.random.randint(1, high=d_max + 1, size=(ndim))

            x = np.array(np.random.normal(size=dims), dtype=dtype)
            x = np.asfortranarray(x)

            X = rfft(x, axis=axis, norm=norm, scrambled=scrambled)

            Y = np.fft.rfft(x, axis=axis, norm=norm)

            x_ = irfft(X,
                       n=x.shape[axis],
                       axis=axis,
                       norm=norm,
                       scrambled=scrambled)

            if not np.allclose(X, Y):
                print(
                    '  Failed forward with ndim=%d axis=%d dims=' %
                    (ndim, axis), dims)
                passed = False

            if not np.allclose(x, x_):
                print(
                    '  Failed backward with ndim=%d axis=%d dims=' %
                    (ndim, axis), dims)
                passed = False

        self.assertTrue(passed)
Exemplo n.º 11
0
    def analysis(self, x):
        """
        Perform frequency analysis of a real input using DFT.

        Parameters
        ----------
        x: numpy array (float32)
            Real input signal in time domain. Must be of size (N,D).
        plot_spec: bool
            Whether or not to plot frequency magnitude spectrum.

        Returns
        -------
        Frequency spectrum, numpy array of size (N/2+1,D) and of type complex64.
        """

        # check for valid input
        if self.D!=1:
            if x.shape!=(self.nfft,self.D):
                raise ValueError('Invalid input dimensions.')
        elif self.D==1:
            if x.ndim!=1 and x.shape[0]!=self.nfft:
                raise ValueError('Invalid input dimensions.')
        # apply window if needed
        if self.analysis_window is not None:
            try:
                np.multiply(self.analysis_window, x, x)
            except:
                self.analysis_window = self.analysis_window.astype(x.dtype, 
                    copy=False)
                np.multiply(self.analysis_window, x, x)
        # apply DFT
        if self.transform == 'fftw':
            self.a[:,] = x
            self.X[:,] = self.forward()
        elif self.transform == 'mkl':
            self.X[:,] = mkl_fft.rfft(x,axis=0)
        else:
            self.X[:,] = rfft(x,axis=0)

        return self.X
Exemplo n.º 12
0
 def test2(self):
     x = self.v1.copy()
     f1 = mkl_fft.irfft(x)
     f2 = mkl_fft.rfft(f1)
     assert_allclose(f2,x)
Exemplo n.º 13
0
def wiener_deconvolve(y,
                      x,
                      length=None,
                      noise_variance=1.,
                      let_n_points=15,
                      let_div_base=2):
    '''
    Deconvolve an excitation signal from an impulse response

    We use Wiener filter

    Parameters
    ----------

    y : ndarray
        The recording
    x : ndarray
        The excitation signal
    length: int, optional
        the length of the impulse response to deconvolve
    noise_variance : float, optional
        estimate of the noise variance
    let_n_points: int
        number of points to use in the LET approximation
    let_div_base: float
        the divider used for the LET grid
    '''

    # FFT length including zero padding
    n = y.shape[0] + x.shape[0] - 1

    # let FFT size be even for convenience
    if n % 2 != 0:
        n += 1

    # when unknown, pick the filter size as size of test signal
    if length is None:
        length = n

    # Forward transforms
    Y = fft.rfft(np.array(y, dtype=np.float32), n=n) / np.sqrt(n)  # recording
    X = fft.rfft(np.array(x, dtype=np.float32), n=n) / np.sqrt(
        n)  # test signal

    # Squared amplitude of test signal
    X_sqm = np.abs(X)**2

    # approximate SNR
    SNR_hat = np.maximum(1e-7, ((np.linalg.norm(Y)**2 / np.linalg.norm(X)**2) -
                                noise_variance)) / noise_variance
    dividers = let_div_base**np.linspace(-let_n_points / 2, let_n_points,
                                         let_n_points)
    SNR_grid = SNR_hat / dividers

    # compute candidate points
    G = (X_sqm[:, None] /
         (X_sqm[:, None] + 1. / SNR_grid[None, :])) * Y[:, None]
    H_candidates = G / X[:, None]

    # find the best linear combination of the candidates
    weights = np.linalg.lstsq(G, Y)[0]

    # compute the estimated filter
    H = np.squeeze(np.dot(H_candidates, weights))
    h = fft.irfft(H, n=n)

    return h[:length]