def test_psd(): n_times = data.shape[-1] freqs, pxx = signal.welch(data, sfreq, window=signal.get_window('boxcar', n_times), return_onesided=True, scaling='spectrum') ps, freqs2 = power_spectrum(sfreq, data, return_db=False) assert_almost_equal(freqs, freqs2) assert_almost_equal(pxx, ps)
def test_psd(): n_channels, n_times = data.shape _data = data[None, ...] # Only test output shape when `method='welch'` or `method='multitaper'` # since it is actually just a wrapper for MNE functions: psd_welch, _ = power_spectrum(sfreq, _data, psd_method='welch') psd_multitaper, _ = power_spectrum(sfreq, _data, psd_method='multitaper') psd_fft, freqs_fft = power_spectrum(sfreq, _data, psd_method='fft') assert_equal(psd_welch.shape, (1, n_channels, n_times // 2 + 1)) assert_equal(psd_multitaper.shape, (1, n_channels, n_times // 2 + 1)) assert_equal(psd_fft.shape, (1, n_channels, n_times // 2 + 1)) # Compare result obtained with `method='fft'` to the Scipy's result # (implementation of Welch's method with rectangular window): expected_freqs, expected_psd = signal.welch(data, sfreq, window=signal.get_window( 'boxcar', data.shape[-1]), return_onesided=True, scaling='density') assert_almost_equal(expected_freqs, freqs_fft) assert_almost_equal(expected_psd, psd_fft[0, ...])
def test_power_spectrum(): ps, freqs = power_spectrum(sfreq, data, return_db=False) _data = data - np.mean(data, axis=-1)[:, None] assert_almost_equal(np.mean(_data ** 2, axis=-1), np.sum(ps, axis=-1))
raw.filter(.5, None, fir_design='firwin') ############################################################################### # Estimate the slope (and the intercept) of the PSD. We use here a single # MEG channel during the full recording to estimate the slope and the # intercept. data, _ = raw[0, :2048] # data = epochs.get_data()[0, 1, :].reshape((1, -1)) sfreq = raw.info['sfreq'] # Compute the (one-sided) PSD using FFT. The ``mask`` variable allows to # select only the part of the PSD which corresponds to frequencies between # 0.1Hz and 40Hz (the data used in this example is already low-pass filtered # at 40Hz). psd, freqs = power_spectrum(sfreq, data) mask = np.logical_and(0.1 <= freqs, freqs <= 40) psd, freqs = psd[0, mask], freqs[mask] # Estimate the slope (and the intercept) of the PSD. The function # :func:`compute_spect_slope` assumes that the PSD of the signal is of the # form: ``psd[f] = b / (f ** a)``. The coefficients a and b are respectively # called *slope* and *intercept* of the Power Spectral Density. The values of # the variables ``slope`` and ``intercept`` differ from the values returned # by ``compute_spect_slope`` because, in the feature function, the linear # regression fit is done in the log10-log10 scale. intercept, slope, _, _ = compute_spect_slope(sfreq, data, fmin=1., fmax=40.) print('The estimated slope (respectively intercept) is: %1.2f (resp. %1.3e)' % (slope, intercept)) # Plot the PSD together with the ``b / (f ** a)`` curve (estimated decay of