예제 #1
0
    def welch(self, x, nfft, pad_to, sampRate):
        window = mlab.window_hanning
        x = np.asarray(x)

        numFreqs = pad_to
        if pad_to % 2:
            freqcenter = (pad_to - 1)//2 + 1
        else:
            freqcenter = pad_to//2

        # Split input vector into slices
        temp = stride_windows(x, nfft, nfft/2, axis=0)

        # Apply window function
        temp, windowVal = apply_window(temp, window, axis=0, return_window=True)

        # Calculate window normalization
        S_1 = (np.abs(windowVal)).sum()

        # Calculate FFT
        power = np.fft.fft(temp, pad_to, axis=0)[:numFreqs, :]

        freqs = np.fft.fftfreq(pad_to, 1/sampRate)[:numFreqs]

        power = np.conjugate(power) * power
        power /= S_1**2

        freqs = np.concatenate((freqs[freqcenter:], freqs[:freqcenter]))
        power = np.concatenate((power[freqcenter:, :], power[:freqcenter, :]), 0)

        # Average the power spectra
        power = np.mean(power, axis=1)
        power = power.real

        return power, freqs
예제 #2
0
def partition(xs, dt, taumax=None, noverlap=0):
    """Split xs into chunks overlapping by `noverlap` points.
    Each chunk is length taumax for xs collected at a sample rate of 1/dt"""
    if taumax is None:
        taumax = (xs.size - 1)*dt
    Npts = min(len(xs), int(taumax/dt))
    xpart = stride_windows(xs, n=Npts, noverlap=noverlap, axis=0).T
    return xpart
예제 #3
0
    def test_stride_windows_n32_noverlap0_unflatten(self, axis):
        n = 32
        x = np.arange(n)[np.newaxis]
        x1 = np.tile(x, (21, 1))
        x2 = x1.flatten()
        y = mlab.stride_windows(x2, n, axis=axis)

        if axis == 0:
            x1 = x1.T
        assert y.shape == x1.shape
        assert_array_equal(y, x1)
예제 #4
0
    def test_stride_windows(self, n, noverlap, axis):
        x = np.arange(100)
        y = mlab.stride_windows(x, n, noverlap=noverlap, axis=axis)

        expected_shape = [0, 0]
        expected_shape[axis] = n
        expected_shape[1 - axis] = 100 // (n - noverlap)
        yt = self.calc_window_target(x, n, noverlap=noverlap, axis=axis)

        assert yt.shape == y.shape
        assert_array_equal(yt, y)
        assert tuple(expected_shape) == y.shape
        assert self.get_base(y) is x
예제 #5
0
    def welch(self, x, nfft, pad_to, sampRate):
        window = mlab.window_hanning
        x = np.asarray(x)

        numFreqs = pad_to
        if pad_to % 2:
            freqcenter = (pad_to - 1) // 2 + 1
        else:
            freqcenter = pad_to // 2

        # Split input vector into slices
        temp = stride_windows(x, nfft, nfft / 2, axis=0)

        # Apply window function
        temp, windowVal = apply_window(temp,
                                       window,
                                       axis=0,
                                       return_window=True)

        # Calculate window normalization
        S_1 = (np.abs(windowVal)).sum()

        # Calculate FFT
        power = np.fft.fft(temp, pad_to, axis=0)[:numFreqs, :]

        freqs = np.fft.fftfreq(pad_to, 1 / sampRate)[:numFreqs]

        power = np.conjugate(power) * power
        power /= S_1**2

        freqs = np.concatenate((freqs[freqcenter:], freqs[:freqcenter]))
        power = np.concatenate((power[freqcenter:, :], power[:freqcenter, :]),
                               0)

        # Average the power spectra
        power = np.mean(power, axis=1)
        power = power.real

        return power, freqs
예제 #6
0
파일: sigproc.py 프로젝트: vhmar/seisk
def window(x, n, samprate, overlap, normalize=True, KOsmooth=False,
           window_correction=None, KOnormalize=False,
           bandwidth=40, detrend=True, subtractmean=False,
           winlen=201, polyorder=3):
    """
    Windowing borrowed from matplotlib.mlab for specgram (_spectral_helper)
    Applies hanning window (if use 0.5 overlap, amplitudes are ~preserved)
    https://github.com/matplotlib/matplotlib/blob/f92bd013ea8f0f99d2e177fd572b86f3b42bb652/lib/matplotlib/mlab.py#L434

    DIVIDES BY NFFT TO CORRECT AMPLITUDES

    Args:
        x (array): 1xn array data to window
        n (int): length each window should be, in samples (before padding)
        overlap (float): proportion of overlap of windows, should be between 0 and 1
        normalize (bool): if True, will normalize by signal length by dividing by 1/NFFT (1/NFFT = deltat/time length),
            if False, will scale by deltat (1/samprate) to approximate continuous transform
        samprate (float): sampling rate of x, in samples per second
        KOsmooth (bool): If True, will return Konno Ohmachi smoothed spectra with only positive frequencies
        window_correction (str): Apply correction for fourier spectrum to account for windowing. If 'amp', will
            multiply spectrum by 2 to preserve amplitude, if 'energy' will multiply by 1.63
        normalize (bool): If True, KOsmooth will be smoothed linearly, otherwise will be smooth logarithmically
        bandwidth (float): bandwidth for KO smoothing
        detrend (bool): if True, will detrend each window
        subtractmean (bool): if True, will subtract time-averaged mean from
            entire time series before windowing using savgol filter
        winlen
        polyorder

    Returns:
        tmid: time vector taken at midpoints of each window (in sec from 0)
        tstart: time vector taken at beginning of each window (in sec from 0)
        freqs: vector of frequency (Hz), applyFT and applyKOsmooth are False, will return None
        resultF: fourier transform, or smoothed fourier transform of each time window
        resultT: time series of each time window (note, will have hanning window applied)

    """
    if overlap < 0. or overlap > 1.:
        raise Exception('overlap must be between 0 and 1')

    if subtractmean:
        mean1 = savgol_filter(np.copy(x), winlen, polyorder)
        x = np.copy(x) - mean1

    noverlap = int(overlap * n)
    resultT1 = mlab.stride_windows(x, n, noverlap)
    row, col = np.shape(resultT1)
    newsampint = (n-noverlap)/samprate
    tstart = np.linspace(0, (col-1)*newsampint, num=col)
    tmid = tstart + 0.5*(n/samprate)  # shift by half of window length
    NFFT = nextpow2(n)
    if detrend:
        resultT = mlab.detrend(resultT1, key='mean', axis=0)
    else:
        resultT = resultT1
    resultTwin, windowVals = mlab.apply_window(resultT, mlab.window_hanning, axis=0, return_window=True)
    if KOsmooth:
        if normalize:
            resultF = np.fft.rfft(resultTwin, n=NFFT, axis=0)/NFFT
        else:
            resultF = np.fft.rfft(resultTwin, n=NFFT, axis=0)/samprate
        if window_correction == 'amp':  # For hanning window
            resultF *= 2.0
        elif window_correction == 'energy':
            resultF *= 1.63
        freqs = np.fft.rfftfreq(NFFT, 1/samprate)
        resultF = ksmooth(np.abs(resultF.T), freqs, normalize=KOnormalize, bandwidth=bandwidth)
        resultF = resultF.T
    else:
        if normalize:
            resultF = np.fft.fft(resultTwin, n=NFFT, axis=0)/NFFT
        else:
            resultF = np.fft.fft(resultTwin, n=NFFT, axis=0)/samprate
        freqs = np.fft.fftfreq(NFFT, 1/samprate)
        if window_correction == 'amp':
            resultF *= 2.0
        elif window_correction == 'energy':
            resultF *= 1.63
    return tmid, tstart, freqs, resultF, resultT, resultTwin
예제 #7
0
 def test_stride_windows_invalid_params(self, n, noverlap):
     x = np.arange(10)
     with pytest.raises(ValueError):
         mlab.stride_windows(x, n, noverlap)
예제 #8
0
 def test_stride_windows_invalid_input_shape(self, shape):
     x = np.arange(np.prod(shape)).reshape(shape)
     with pytest.raises(ValueError):
         mlab.stride_windows(x, 5)
예제 #9
0
파일: ensemble.py 프로젝트: emd/random_data
    def getFFTs(self, x, detrend=mlab.detrend_none,
                window=mlab.window_hanning):
        '''Get array of FFTs corresponding to each realization of `x`.

        Parameters:
        -----------
        x - array_like, (`N`,)
            Signal to be analyzed. Signal is split into several
            realizations, and the FFT of each realization is computed.
            [x] = arbitrary units

        detrend - string
            The function applied to each realization before taking FFT.
            May be [ 'default' | 'constant' | 'mean' | 'linear' | 'none']
            or callable, as specified in :py:func: `csd <matplotlib.mlab.csd>`.

            *Warning*: Naively detrending (even with something as simple as
            `mean` or `linear` detrending) can introduce detrimental artifacts
            into the computed spectrum, so *no* detrending is the default.

        window - callable or ndarray
            The window applied to each realization before taking FFT,
            as specified in :py:func: `csd <matplotlib.mlab.csd>`.

        Returns:
        --------
        Xk - array_like, (L, M, N) where
                L = `len(self.f)` = `(self.Npts_per_real // 2) + 1`,
                M = number of whole ensembles in data record `x`, and
                N = `self.Nreal_per_ens`

            The FFTs of each realization in each ensemble.
            The FFTs are indexed by frequency, ensemble, and realization.

            [Xk] = [x]

        '''
        # Only real-valued signals are expected/supported at the moment
        if np.iscomplexobj(x):
            raise ValueError('`x` must be a real-valued signal!')

        # Determine the number of *whole* ensembles in the data record
        # (Disregard fractional ensemble at the end of the data, if present)
        Nens = np.int(len(x) / self.Npts_per_ens)

        # Determine number of frequencies in 1-sided FFT, noting that
        # `self.Npts_per_real` is constrained to be a power of 2
        Nf = (self.Npts_per_real // 2) + 1

        # Initialize.
        Xk = np.zeros(
            (Nf, Nens, self.Nreal_per_ens),
            dtype='complex')

        # Loop through each ensemble, computing the FFT of each realization
        # via strides for efficient use of memory. (Note that the below
        # procedure closely parallels that of Matplotlib's internal function
        #
        #     :py:func:`_spectral_helper <matplotlib.mlab._spectral_helper>`
        #
        # Here, we use our own implementation so as not to rely on
        # an internal function)
        stride_axis = 0
        for ens in np.arange(Nens):
            # Split the ensemble into realizations
            sl = slice(
                ens * self.Npts_per_ens,
                (ens + 1) * self.Npts_per_ens)

            result = mlab.stride_windows(
                x[sl],
                self.Npts_per_real,
                self.Npts_overlap,
                axis=stride_axis)

            # Detrend each realization
            result = mlab.detrend(
                result,
                detrend,
                axis=stride_axis)

            # Window each realization (power loss compensated outside loop)
            result, windowVals = mlab.apply_window(
                result,
                window,
                axis=stride_axis,
                return_window=True)

            # Finally compute and return the FFT of each realization
            Xk[:, ens, :] = np.fft.rfft(result, axis=stride_axis)

        # Compensate for windowing power loss
        norm = np.sqrt(np.mean((np.abs(windowVals)) ** 2))
        Xk /= norm

        return Xk
예제 #10
0
    def getFFTs(self,
                x,
                detrend=mlab.detrend_none,
                window=mlab.window_hanning):
        '''Get array of FFTs corresponding to each realization of `x`.

        Parameters:
        -----------
        x - array_like, (`N`,)
            Signal to be analyzed. Signal is split into several
            realizations, and the FFT of each realization is computed.
            [x] = arbitrary units

        detrend - string
            The function applied to each realization before taking FFT.
            May be [ 'default' | 'constant' | 'mean' | 'linear' | 'none']
            or callable, as specified in :py:func: `csd <matplotlib.mlab.csd>`.

            *Warning*: Naively detrending (even with something as simple as
            `mean` or `linear` detrending) can introduce detrimental artifacts
            into the computed spectrum, so *no* detrending is the default.

        window - callable or ndarray
            The window applied to each realization before taking FFT,
            as specified in :py:func: `csd <matplotlib.mlab.csd>`.

        Returns:
        --------
        Xk - array_like, (L, M, N) where
                L = `len(self.f)` = `(self.Npts_per_real // 2) + 1`,
                M = number of whole ensembles in data record `x`, and
                N = `self.Nreal_per_ens`

            The FFTs of each realization in each ensemble.
            The FFTs are indexed by frequency, ensemble, and realization.

            [Xk] = [x]

        '''
        # Only real-valued signals are expected/supported at the moment
        if np.iscomplexobj(x):
            raise ValueError('`x` must be a real-valued signal!')

        # Determine the number of *whole* ensembles in the data record
        # (Disregard fractional ensemble at the end of the data, if present)
        Nens = np.int(len(x) / self.Npts_per_ens)

        # Determine number of frequencies in 1-sided FFT, noting that
        # `self.Npts_per_real` is constrained to be a power of 2
        Nf = (self.Npts_per_real // 2) + 1

        # Initialize.
        Xk = np.zeros((Nf, Nens, self.Nreal_per_ens), dtype='complex')

        # Loop through each ensemble, computing the FFT of each realization
        # via strides for efficient use of memory. (Note that the below
        # procedure closely parallels that of Matplotlib's internal function
        #
        #     :py:func:`_spectral_helper <matplotlib.mlab._spectral_helper>`
        #
        # Here, we use our own implementation so as not to rely on
        # an internal function)
        stride_axis = 0
        for ens in np.arange(Nens):
            # Split the ensemble into realizations
            sl = slice(ens * self.Npts_per_ens, (ens + 1) * self.Npts_per_ens)

            result = mlab.stride_windows(x[sl],
                                         self.Npts_per_real,
                                         self.Npts_overlap,
                                         axis=stride_axis)

            # Detrend each realization
            result = mlab.detrend(result, detrend, axis=stride_axis)

            # Window each realization (power loss compensated outside loop)
            result, windowVals = mlab.apply_window(result,
                                                   window,
                                                   axis=stride_axis,
                                                   return_window=True)

            # Finally compute and return the FFT of each realization
            Xk[:, ens, :] = np.fft.rfft(result, axis=stride_axis)

        # Compensate for windowing power loss
        norm = np.sqrt(np.mean((np.abs(windowVals))**2))
        Xk /= norm

        return Xk