def make_notch( Fs, center, width=1 ): # Assure lower boundary is not too low Fp1 = max(center-width/2., 0.1) Fp2 = center+width/2. iir_params = _check_method('iir', None, []) Fp1 = np.atleast_1d(Fp1) Fp2 = np.atleast_1d(Fp2) if not len(Fp1) == len(Fp2): raise ValueError('Fp1 and Fp2 must be the same length') Fs = float(Fs) Fp1 = Fs1 = Fp1.astype(float) Fp2 = Fs2 = Fp2.astype(float) if np.any(Fs1 <= 0): raise ValueError('Filter specification invalid: Lower stop frequency ' 'too low (%0.1fHz). Increase Fp1 or reduce ' 'transition bandwidth (l_trans_bandwidth)' % Fs1) for fp_1, fp_2, fs_1, fs_2 in zip(Fp1, Fp2, Fs1, Fs2): iir_params_new = construct_iir_filter(iir_params, [fp_1, fp_2], [fs_1, fs_2], Fs, 'bandstop') iir_params_new = dict(order=4, ftype='butter') iir_params_new = construct_iir_filter(iir_params, [center-1, center], [center, center+1], Fs, 'bandstop', return_copy=False) # b, a = signal.butter(2,bp_stop_Hz/(fs_Hz / 2.0), 'bandstop') return iir_params_new['b'], iir_params_new['a']
def make_notch(Fs, center, width=1): # Assure lower boundary is not too low Fp1 = max(center - width / 2., 0.1) Fp2 = center + width / 2. iir_params = _check_method('iir', None, []) Fp1 = np.atleast_1d(Fp1) Fp2 = np.atleast_1d(Fp2) if not len(Fp1) == len(Fp2): raise ValueError('Fp1 and Fp2 must be the same length') Fs = float(Fs) Fp1 = Fs1 = Fp1.astype(float) Fp2 = Fs2 = Fp2.astype(float) if np.any(Fs1 <= 0): raise ValueError('Filter specification invalid: Lower stop frequency ' 'too low (%0.1fHz). Increase Fp1 or reduce ' 'transition bandwidth (l_trans_bandwidth)' % Fs1) for fp_1, fp_2, fs_1, fs_2 in zip(Fp1, Fp2, Fs1, Fs2): iir_params_new = construct_iir_filter(iir_params, [fp_1, fp_2], [fs_1, fs_2], Fs, 'bandstop') iir_params_new = dict(order=4, ftype='butter') iir_params_new = construct_iir_filter(iir_params, [center - 1, center], [center, center + 1], Fs, 'bandstop', return_copy=False) # b, a = signal.butter(2,bp_stop_Hz/(fs_Hz / 2.0), 'bandstop') return iir_params_new['b'], iir_params_new['a']
def make_notch( Fs, center, width=1 ): Fp1 = center-width/2. Fp2 = center+width/2. iir_params = _check_method('iir', None, []) print iir_params Fp1 = np.atleast_1d(Fp1) Fp2 = np.atleast_1d(Fp2) if not len(Fp1) == len(Fp2): raise ValueError('Fp1 and Fp2 must be the same length') Fs = float(Fs) Fp1 = Fs1 = Fp1.astype(float) Fp2 = Fs2 = Fp2.astype(float) if np.any(Fs1 <= 0): raise ValueError('Filter specification invalid: Lower stop frequency ' 'too low (%0.1fHz). Increase Fp1 or reduce ' 'transition bandwidth (l_trans_bandwidth)' % Fs1) for fp_1, fp_2, fs_1, fs_2 in zip(Fp1, Fp2, Fs1, Fs2): iir_params_new = construct_iir_filter(iir_params, [fp_1, fp_2], [fs_1, fs_2], Fs, 'bandstop') return iir_params_new['b'], iir_params_new['a']
def test_iir_stability(): """Test IIR filter stability check.""" sig = np.empty(1000) sfreq = 1000 # This will make an unstable filter, should throw RuntimeError assert_raises(RuntimeError, high_pass_filter, sig, sfreq, 0.6, method='iir', iir_params=dict(ftype='butter', order=8, output='ba')) # This one should work just fine high_pass_filter(sig, sfreq, 0.6, method='iir', iir_params=dict(ftype='butter', order=8, output='sos')) # bad system type assert_raises(ValueError, high_pass_filter, sig, sfreq, 0.6, method='iir', iir_params=dict(ftype='butter', order=8, output='foo')) # missing ftype assert_raises(RuntimeError, high_pass_filter, sig, sfreq, 0.6, method='iir', iir_params=dict(order=8, output='sos')) # bad ftype assert_raises(RuntimeError, high_pass_filter, sig, sfreq, 0.6, method='iir', iir_params=dict(order=8, ftype='foo', output='sos')) # missing gstop assert_raises(RuntimeError, high_pass_filter, sig, sfreq, 0.6, method='iir', iir_params=dict(gpass=0.5, output='sos')) # can't pass iir_params if method='fft' assert_raises(ValueError, high_pass_filter, sig, sfreq, 0.1, method='fft', iir_params=dict(ftype='butter', order=2, output='sos')) # method must be string assert_raises(TypeError, high_pass_filter, sig, sfreq, 0.1, method=1) # unknown method assert_raises(ValueError, high_pass_filter, sig, sfreq, 0.1, method='blah') # bad iir_params assert_raises(TypeError, high_pass_filter, sig, sfreq, 0.1, method='iir', iir_params='blah') assert_raises(ValueError, high_pass_filter, sig, sfreq, 0.1, method='fft', iir_params=dict()) # should pass because dafault trans_bandwidth is not relevant iir_params = dict(ftype='butter', order=2, output='sos') x_sos = high_pass_filter(sig, 250, 0.5, method='iir', iir_params=iir_params) iir_params_sos = construct_iir_filter(iir_params, f_pass=0.5, sfreq=250, btype='highpass') x_sos_2 = high_pass_filter(sig, 250, 0.5, method='iir', iir_params=iir_params_sos) assert_allclose(x_sos[100:-100], x_sos_2[100:-100]) x_ba = high_pass_filter(sig, 250, 0.5, method='iir', iir_params=dict(ftype='butter', order=2, output='ba')) # Note that this will fail for higher orders (e.g., 6) showing the # hopefully decreased numerical error of SOS assert_allclose(x_sos[100:-100], x_ba[100:-100])
def test_iir_stability(): """Test IIR filter stability check.""" sig = np.random.RandomState(0).rand(1000) sfreq = 1000 # This will make an unstable filter, should throw RuntimeError pytest.raises(RuntimeError, filter_data, sig, sfreq, 0.6, None, method='iir', iir_params=dict(ftype='butter', order=8, output='ba')) # This one should work just fine filter_data(sig, sfreq, 0.6, None, method='iir', iir_params=dict(ftype='butter', order=8, output='sos')) # bad system type pytest.raises(ValueError, filter_data, sig, sfreq, 0.6, None, method='iir', iir_params=dict(ftype='butter', order=8, output='foo')) # missing ftype pytest.raises(RuntimeError, filter_data, sig, sfreq, 0.6, None, method='iir', iir_params=dict(order=8, output='sos')) # bad ftype pytest.raises(RuntimeError, filter_data, sig, sfreq, 0.6, None, method='iir', iir_params=dict(order=8, ftype='foo', output='sos')) # missing gstop pytest.raises(RuntimeError, filter_data, sig, sfreq, 0.6, None, method='iir', iir_params=dict(gpass=0.5, output='sos')) # can't pass iir_params if method='fft' pytest.raises(ValueError, filter_data, sig, sfreq, 0.1, None, method='fft', iir_params=dict(ftype='butter', order=2, output='sos')) # method must be string pytest.raises(TypeError, filter_data, sig, sfreq, 0.1, None, method=1) # unknown method pytest.raises(ValueError, filter_data, sig, sfreq, 0.1, None, method='blah') # bad iir_params pytest.raises(TypeError, filter_data, sig, sfreq, 0.1, None, method='iir', iir_params='blah') pytest.raises(ValueError, filter_data, sig, sfreq, 0.1, None, method='fir', iir_params=dict()) # should pass because default trans_bandwidth is not relevant iir_params = dict(ftype='butter', order=2, output='sos') x_sos = filter_data(sig, 250, 0.5, None, method='iir', iir_params=iir_params) iir_params_sos = construct_iir_filter(iir_params, f_pass=0.5, sfreq=250, btype='highpass') x_sos_2 = filter_data(sig, 250, 0.5, None, method='iir', iir_params=iir_params_sos) assert_allclose(x_sos[100:-100], x_sos_2[100:-100]) x_ba = filter_data(sig, 250, 0.5, None, method='iir', iir_params=dict(ftype='butter', order=2, output='ba')) # Note that this will fail for higher orders (e.g., 6) showing the # hopefully decreased numerical error of SOS assert_allclose(x_sos[100:-100], x_ba[100:-100])
def _make_lowpass( self, Fs, lowpass ): """ Taken from mne filter package Generates IIR A and B parameters based on the sample frequency and the cutoff frequency """ iir_params = _check_method('iir', None, []) Fs = float(Fs) lowpass = float(lowpass) if lowpass > Fs / 2.: raise ValueError('Effective stop frequency (%s) is too high ' '(maximum based on Nyquist is %s)' % (lowpass, Fs / 2.)) iir_params = construct_iir_filter(iir_params, lowpass, lowpass, Fs, 'low') return iir_params['b'], iir_params['a']
def _make_lowpass(self, Fs, lowpass): """ Taken from mne filter package Generates IIR A and B parameters based on the sample frequency and the cutoff frequency """ iir_params = _check_method('iir', None, []) Fs = float(Fs) lowpass = float(lowpass) if lowpass > Fs / 2.: raise ValueError('Effective stop frequency (%s) is too high ' '(maximum based on Nyquist is %s)' % (lowpass, Fs / 2.)) iir_params = construct_iir_filter(iir_params, lowpass, lowpass, Fs, 'low') return iir_params['b'], iir_params['a']
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling.""" rng = np.random.RandomState(0) sfreq = 100 sig_len_secs = 15 a = rng.randn(2, sig_len_secs * sfreq) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: pytest.raises((ValueError, TypeError), filter_data, a, sfreq, 4, 8, None, fl, 1.0, 1.0, fir_design='firwin') with pytest.raises(TypeError, match='got <class'): filter_data(a, sfreq, 4, 8, None, 1000, 1.0, 1.0, n_jobs=0.5, phase='zero', fir_design='firwin') with pytest.raises(ValueError, match='Invalid value'): filter_data(a, sfreq, 4, 8, None, 1000, 1.0, 1.0, n_jobs='blah', phase='zero', fir_design='firwin') pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, None, 100, 1., 1., fir_window='foo') pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, None, 10, 1., 1., fir_design='firwin') # too short # > Nyq/2 pytest.raises(ValueError, filter_data, a, sfreq, 4, sfreq / 2., None, 100, 1.0, 1.0, fir_design='firwin') pytest.raises(ValueError, filter_data, a, sfreq, -1, None, None, 100, 1.0, 1.0, fir_design='firwin') # these should work create_filter(None, sfreq, None, None) create_filter(a, sfreq, None, None, fir_design='firwin') create_filter(a, sfreq, None, None, method='iir') # check our short-filter warning: with pytest.warns(RuntimeWarning, match='attenuation'): # Warning for low attenuation filter_data(a, sfreq, 1, 8, filter_length=256, fir_design='firwin2') with pytest.warns(RuntimeWarning, match='Increase filter_length'): # Warning for too short a filter filter_data(a, sfreq, 1, 8, filter_length='0.5s', fir_design='firwin2') # try new default and old default freqs = fftfreq(a.shape[-1], 1. / sfreq) A = np.abs(fft(a)) kwargs = dict(fir_design='firwin') for fl in ['auto', '10s', '5000ms', 1024, 1023]: bp = filter_data(a, sfreq, 4, 8, None, fl, 1.0, 1.0, **kwargs) bs = filter_data(a, sfreq, 8 + 1.0, 4 - 1.0, None, fl, 1.0, 1.0, **kwargs) lp = filter_data(a, sfreq, None, 8, None, fl, 10, 1.0, n_jobs=2, **kwargs) hp = filter_data(lp, sfreq, 4, None, None, fl, 1.0, 10, **kwargs) assert_allclose(hp, bp, rtol=1e-3, atol=2e-3) assert_allclose(bp + bs, a, rtol=1e-3, atol=1e-3) # Sanity check ttenuation mask = (freqs > 5.5) & (freqs < 6.5) assert_allclose(np.mean(np.abs(fft(bp)[:, mask]) / A[:, mask]), 1., atol=0.02) assert_allclose(np.mean(np.abs(fft(bs)[:, mask]) / A[:, mask]), 0., atol=0.2) # now the minimum-phase versions bp = filter_data(a, sfreq, 4, 8, None, fl, 1.0, 1.0, phase='minimum', **kwargs) bs = filter_data(a, sfreq, 8 + 1.0, 4 - 1.0, None, fl, 1.0, 1.0, phase='minimum', **kwargs) assert_allclose(np.mean(np.abs(fft(bp)[:, mask]) / A[:, mask]), 1., atol=0.11) assert_allclose(np.mean(np.abs(fft(bs)[:, mask]) / A[:, mask]), 0., atol=0.3) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=None bp_up_dn = resample(resample(bp, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp, 2 * bp.shape[-1], axis=-1, window='boxcar'), bp.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(sfreq * sig_len_secs))) / float(sfreq) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * sfreq / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='ba') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert iir_params['a'].size - 1 == 3 assert iir_params['b'].size - 1 == 3 iir_params = dict(ftype='butter', order=4, output='ba') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert iir_params['a'].size - 1 == 4 assert iir_params['b'].size - 1 == 4 iir_params = dict(ftype='cheby1', gpass=1, gstop=20) iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter, which requires 2 SOS ((2, 6)) assert iir_params['sos'].shape == (2, 6) iir_params = dict(ftype='butter', order=4, output='sos') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert iir_params['sos'].shape == (2, 6) # check that picks work for 3d array with one channel and picks=[0] a = rng.randn(5 * sfreq, 5 * sfreq) b = a[:, None, :] a_filt = filter_data(a, sfreq, 4, 8, None, 400, 2.0, 2.0, fir_design='firwin') b_filt = filter_data(b, sfreq, 4, 8, [0], 400, 2.0, 2.0, fir_design='firwin') assert_array_equal(a_filt[:, None, :], b_filt) # check for n-dimensional case a = rng.randn(2, 2, 2, 2) with pytest.warns(RuntimeWarning, match='longer'): pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, np.array([0, 1]), 100, 1.0, 1.0) # check corner case (#4693) want_length = int(round(_length_factors['hamming'] * 1000. / 0.5)) want_length += (want_length % 2 == 0) assert want_length == 6601 h = create_filter(np.empty(10000), 1000., l_freq=None, h_freq=55., h_trans_bandwidth=0.5, method='fir', phase='zero-double', fir_design='firwin', verbose=True) assert len(h) == 6601 h = create_filter(np.empty(10000), 1000., l_freq=None, h_freq=55., h_trans_bandwidth=0.5, method='fir', phase='zero', fir_design='firwin', filter_length='7s', verbose=True) assert len(h) == 7001 h = create_filter(np.empty(10000), 1000., l_freq=None, h_freq=55., h_trans_bandwidth=0.5, method='fir', phase='zero-double', fir_design='firwin', filter_length='7s', verbose=True) assert len(h) == 8193 # next power of two
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling.""" sfreq = 100 sig_len_secs = 15 a = rng.randn(2, sig_len_secs * sfreq) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, fl, 1., 1.) for nj in ['blah', 0.5]: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, 100, 1., 1., n_jobs=nj) assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, 100, 1., 1., fir_window='foo') # > Nyq/2 assert_raises(ValueError, band_pass_filter, a, sfreq, 4, sfreq / 2., 100, 1.0, 1.0) assert_raises(ValueError, low_pass_filter, a, sfreq, sfreq / 2., 100, 1.0) # check our short-filter warning: with warnings.catch_warnings(record=True) as w: # Warning for low attenuation band_pass_filter(a, sfreq, 1, 8, filter_length=256) assert_true(any('attenuation' in str(ww.message) for ww in w)) with warnings.catch_warnings(record=True) as w: # Warning for too short a filter band_pass_filter(a, sfreq, 1, 8, filter_length='0.5s') assert_true(any('Increase filter_length' in str(ww.message) for ww in w)) # try new default and old default for fl in ['auto', '10s', '5000ms', 1024]: bp = band_pass_filter(a, sfreq, 4, 8, fl, 1.0, 1.0) bs = band_stop_filter(a, sfreq, 4 - 1.0, 8 + 1.0, fl, 1.0, 1.0) lp = low_pass_filter(a, sfreq, 8, fl, 1.0, n_jobs=2) hp = high_pass_filter(lp, sfreq, 4, fl, 1.0) assert_array_almost_equal(hp, bp, 4) assert_array_almost_equal(bp + bs, a, 4) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp, 2 * bp.shape[-1], axis=-1, window='boxcar'), bp.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(sfreq * sig_len_secs))) / float(sfreq) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * sfreq / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='ba') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_equal(iir_params['a'].size - 1, 3) assert_equal(iir_params['b'].size - 1, 3) iir_params = dict(ftype='butter', order=4, output='ba') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_equal(iir_params['a'].size - 1, 4) assert_equal(iir_params['b'].size - 1, 4) iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='sos') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter, which requires 2 SOS ((2, 6)) assert_equal(iir_params['sos'].shape, (2, 6)) iir_params = dict(ftype='butter', order=4, output='sos') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_equal(iir_params['sos'].shape, (2, 6)) # check that picks work for 3d array with one channel and picks=[0] a = rng.randn(5 * sfreq, 5 * sfreq) b = a[:, None, :] a_filt = band_pass_filter(a, sfreq, 4, 8, 400, 2.0, 2.0) b_filt = band_pass_filter(b, sfreq, 4, 8, 400, 2.0, 2.0, picks=[0]) assert_array_equal(a_filt[:, None, :], b_filt) # check for n-dimensional case a = rng.randn(2, 2, 2, 2) with warnings.catch_warnings(record=True): # filter too long assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, 100, 1.0, 1.0, picks=np.array([0, 1]))
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling """ Fs = 500 sig_len_secs = 30 a = np.random.randn(2, sig_len_secs * Fs) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: assert_raises(ValueError, band_pass_filter, a, Fs, 4, 8, filter_length=fl) for nj in ['blah', 0.5, 0]: assert_raises(ValueError, band_pass_filter, a, Fs, 4, 8, n_jobs=nj) assert_raises(ValueError, band_pass_filter, a, Fs, 4, Fs / 2.) # > Nyq/2 assert_raises(ValueError, low_pass_filter, a, Fs, Fs / 2.) # > Nyq/2 # check our short-filter warning: with warnings.catch_warnings(record=True) as w: # Warning for low attenuation band_pass_filter(a, Fs, 1, 8, filter_length=1024) # Warning for too short a filter band_pass_filter(a, Fs, 1, 8, filter_length='0.5s') assert_true(len(w) >= 2) # try new default and old default for fl in ['10s', '5000ms', None]: bp = band_pass_filter(a, Fs, 4, 8, filter_length=fl) bs = band_stop_filter(a, Fs, 4 - 0.5, 8 + 0.5, filter_length=fl) lp = low_pass_filter(a, Fs, 8, filter_length=fl, n_jobs=2) hp = high_pass_filter(lp, Fs, 4, filter_length=fl) assert_array_almost_equal(hp, bp, 2) assert_array_almost_equal(bp + bs, a, 1) # Overlap-add filtering with a fixed filter length filter_length = 8192 bp_oa = band_pass_filter(a, Fs, 4, 8, filter_length) bs_oa = band_stop_filter(a, Fs, 4 - 0.5, 8 + 0.5, filter_length) lp_oa = low_pass_filter(a, Fs, 8, filter_length) hp_oa = high_pass_filter(lp_oa, Fs, 4, filter_length) assert_array_almost_equal(hp_oa, bp_oa, 2) assert_array_almost_equal(bp_oa + bs_oa, a, 2) # The two methods should give the same result # As filtering for short signals uses a circular convolution (FFT) and # the overlap-add filter implements a linear convolution, the signal # boundary will be slightly different and we ignore it n_edge_ignore = 0 assert_array_almost_equal(hp[n_edge_ignore:-n_edge_ignore], hp_oa[n_edge_ignore:-n_edge_ignore], 2) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp_oa, 2 * bp_oa.shape[-1], axis=-1, window='boxcar'), bp_oa.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(Fs * sig_len_secs))) / float(Fs) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * Fs / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20) iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_true(iir_params['a'].size - 1 == 3) assert_true(iir_params['b'].size - 1 == 3) iir_params = dict(ftype='butter', order=4) iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_true(iir_params['a'].size - 1 == 4) assert_true(iir_params['b'].size - 1 == 4)
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling """ Fs = 500 sig_len_secs = 30 a = np.random.randn(2, sig_len_secs * Fs) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: assert_raises(ValueError, band_pass_filter, a, Fs, 4, 8, filter_length=fl) for nj in ['blah', 0.5, 0]: assert_raises(ValueError, band_pass_filter, a, Fs, 4, 8, n_jobs=nj) # check our short-filter warning: with warnings.catch_warnings(record=True) as w: # Warning for low attenuation band_pass_filter(a, Fs, 1, 8, filter_length=1024) # Warning for too short a filter band_pass_filter(a, Fs, 1, 8, filter_length='0.5s') assert_true(len(w) >= 2) # try new default and old default for fl in ['10s', '5000ms', None]: bp = band_pass_filter(a, Fs, 4, 8, filter_length=fl) bs = band_stop_filter(a, Fs, 4 - 0.5, 8 + 0.5, filter_length=fl) lp = low_pass_filter(a, Fs, 8, filter_length=fl, n_jobs=2) hp = high_pass_filter(lp, Fs, 4, filter_length=fl) assert_array_almost_equal(hp, bp, 2) assert_array_almost_equal(bp + bs, a, 1) # Overlap-add filtering with a fixed filter length filter_length = 8192 bp_oa = band_pass_filter(a, Fs, 4, 8, filter_length) bs_oa = band_stop_filter(a, Fs, 4 - 0.5, 8 + 0.5, filter_length) lp_oa = low_pass_filter(a, Fs, 8, filter_length) hp_oa = high_pass_filter(lp_oa, Fs, 4, filter_length) assert_array_almost_equal(hp_oa, bp_oa, 2) assert_array_almost_equal(bp_oa + bs_oa, a, 2) # The two methods should give the same result # As filtering for short signals uses a circular convolution (FFT) and # the overlap-add filter implements a linear convolution, the signal # boundary will be slightly different and we ignore it n_edge_ignore = 0 assert_array_almost_equal(hp[n_edge_ignore:-n_edge_ignore], hp_oa[n_edge_ignore:-n_edge_ignore], 2) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp_oa, 2 * len(bp_oa), window='boxcar'), len(bp_oa), window='boxcar') assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(range(Fs * sig_len_secs)) / float(Fs) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * Fs / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20) iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_true(iir_params['a'].size - 1 == 3) assert_true(iir_params['b'].size - 1 == 3) iir_params = dict(ftype='butter', order=4) iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_true(iir_params['a'].size - 1 == 4) assert_true(iir_params['b'].size - 1 == 4)
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling.""" sfreq = 100 sig_len_secs = 15 a = rng.randn(2, sig_len_secs * sfreq) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, None, fl, 1.0, 1.0, fir_design='firwin') for nj in ['blah', 0.5]: pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, None, 1000, 1.0, 1.0, n_jobs=nj, phase='zero', fir_design='firwin') pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, None, 100, 1., 1., fir_window='foo') pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, None, 10, 1., 1., fir_design='firwin') # too short # > Nyq/2 pytest.raises(ValueError, filter_data, a, sfreq, 4, sfreq / 2., None, 100, 1.0, 1.0, fir_design='firwin') pytest.raises(ValueError, filter_data, a, sfreq, -1, None, None, 100, 1.0, 1.0, fir_design='firwin') # these should work create_filter(None, sfreq, None, None) create_filter(a, sfreq, None, None, fir_design='firwin') create_filter(a, sfreq, None, None, method='iir') # check our short-filter warning: with pytest.warns(RuntimeWarning, match='attenuation'): # Warning for low attenuation filter_data(a, sfreq, 1, 8, filter_length=256, fir_design='firwin2') with pytest.warns(RuntimeWarning, match='Increase filter_length'): # Warning for too short a filter filter_data(a, sfreq, 1, 8, filter_length='0.5s', fir_design='firwin2') # try new default and old default freqs = fftfreq(a.shape[-1], 1. / sfreq) A = np.abs(fft(a)) kwargs = dict(fir_design='firwin') for fl in ['auto', '10s', '5000ms', 1024, 1023]: bp = filter_data(a, sfreq, 4, 8, None, fl, 1.0, 1.0, **kwargs) bs = filter_data(a, sfreq, 8 + 1.0, 4 - 1.0, None, fl, 1.0, 1.0, **kwargs) lp = filter_data(a, sfreq, None, 8, None, fl, 10, 1.0, n_jobs=2, **kwargs) hp = filter_data(lp, sfreq, 4, None, None, fl, 1.0, 10, **kwargs) assert_allclose(hp, bp, rtol=1e-3, atol=1e-3) assert_allclose(bp + bs, a, rtol=1e-3, atol=1e-3) # Sanity check ttenuation mask = (freqs > 5.5) & (freqs < 6.5) assert_allclose(np.mean(np.abs(fft(bp)[:, mask]) / A[:, mask]), 1., atol=0.02) assert_allclose(np.mean(np.abs(fft(bs)[:, mask]) / A[:, mask]), 0., atol=0.2) # now the minimum-phase versions bp = filter_data(a, sfreq, 4, 8, None, fl, 1.0, 1.0, phase='minimum', **kwargs) bs = filter_data(a, sfreq, 8 + 1.0, 4 - 1.0, None, fl, 1.0, 1.0, phase='minimum', **kwargs) assert_allclose(np.mean(np.abs(fft(bp)[:, mask]) / A[:, mask]), 1., atol=0.11) assert_allclose(np.mean(np.abs(fft(bs)[:, mask]) / A[:, mask]), 0., atol=0.3) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp, 2 * bp.shape[-1], axis=-1, window='boxcar'), bp.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(sfreq * sig_len_secs))) / float(sfreq) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * sfreq / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='ba') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert iir_params['a'].size - 1 == 3 assert iir_params['b'].size - 1 == 3 iir_params = dict(ftype='butter', order=4, output='ba') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert iir_params['a'].size - 1 == 4 assert iir_params['b'].size - 1 == 4 iir_params = dict(ftype='cheby1', gpass=1, gstop=20) iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter, which requires 2 SOS ((2, 6)) assert iir_params['sos'].shape == (2, 6) iir_params = dict(ftype='butter', order=4, output='sos') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert iir_params['sos'].shape == (2, 6) # check that picks work for 3d array with one channel and picks=[0] a = rng.randn(5 * sfreq, 5 * sfreq) b = a[:, None, :] a_filt = filter_data(a, sfreq, 4, 8, None, 400, 2.0, 2.0, fir_design='firwin') b_filt = filter_data(b, sfreq, 4, 8, [0], 400, 2.0, 2.0, fir_design='firwin') assert_array_equal(a_filt[:, None, :], b_filt) # check for n-dimensional case a = rng.randn(2, 2, 2, 2) with pytest.warns(RuntimeWarning, match='longer'): pytest.raises(ValueError, filter_data, a, sfreq, 4, 8, np.array([0, 1]), 100, 1.0, 1.0) # check corner case (#4693) h = create_filter( np.empty(10000), 1000., l_freq=None, h_freq=55., h_trans_bandwidth=0.5, method='fir', phase='zero-double', fir_design='firwin', verbose=True) assert len(h) == 6601
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling """ Fs = 500 sig_len_secs = 30 # Filtering of short signals (filter length = len(a)) a = np.random.randn(2, sig_len_secs * Fs) bp = band_pass_filter(a, Fs, 4, 8) bs = band_stop_filter(a, Fs, 4 - 0.5, 8 + 0.5) lp = low_pass_filter(a, Fs, 8) hp = high_pass_filter(lp, Fs, 4) assert_array_almost_equal(hp, bp, 2) assert_array_almost_equal(bp + bs, a, 1) # Overlap-add filtering with a fixed filter length filter_length = 8192 bp_oa = band_pass_filter(a, Fs, 4, 8, filter_length) bs_oa = band_stop_filter(a, Fs, 4 - 0.5, 8 + 0.5, filter_length) lp_oa = low_pass_filter(a, Fs, 8, filter_length) hp_oa = high_pass_filter(lp_oa, Fs, 4, filter_length) assert_array_almost_equal(hp_oa, bp_oa, 2) assert_array_almost_equal(bp_oa + bs_oa, a, 2) # The two methods should give the same result # As filtering for short signals uses a circular convolution (FFT) and # the overlap-add filter implements a linear convolution, the signal # boundary will be slightly different and we ignore it n_edge_ignore = 0 assert_array_almost_equal(hp[n_edge_ignore:-n_edge_ignore], hp_oa[n_edge_ignore:-n_edge_ignore], 2) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp_oa, 2 * len(bp_oa), window='boxcar'), len(bp_oa), window='boxcar') assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(range(Fs * sig_len_secs)) / float(Fs) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * Fs / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20) iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_true(iir_params['a'].size - 1 == 3) assert_true(iir_params['b'].size - 1 == 3) iir_params = dict(ftype='butter', order=4) iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_true(iir_params['a'].size - 1 == 4) assert_true(iir_params['b'].size - 1 == 4)
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling.""" sfreq = 100 sig_len_secs = 15 a = rng.randn(2, sig_len_secs * sfreq) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: assert_raises(ValueError, filter_data, a, sfreq, 4, 8, None, fl, 1.0, 1.0, fir_design='firwin') for nj in ['blah', 0.5]: assert_raises(ValueError, filter_data, a, sfreq, 4, 8, None, 1000, 1.0, 1.0, n_jobs=nj, phase='zero', fir_design='firwin') assert_raises(ValueError, filter_data, a, sfreq, 4, 8, None, 100, 1., 1., fir_window='foo') assert_raises(ValueError, filter_data, a, sfreq, 4, 8, None, 10, 1., 1., fir_design='firwin') # too short # > Nyq/2 assert_raises(ValueError, filter_data, a, sfreq, 4, sfreq / 2., None, 100, 1.0, 1.0, fir_design='firwin') assert_raises(ValueError, filter_data, a, sfreq, -1, None, None, 100, 1.0, 1.0, fir_design='firwin') # these should work create_filter(a, sfreq, None, None, fir_design='firwin') create_filter(a, sfreq, None, None, method='iir') # check our short-filter warning: with warnings.catch_warnings(record=True) as w: # Warning for low attenuation filter_data(a, sfreq, 1, 8, filter_length=256, fir_design='firwin2') assert_true(any('attenuation' in str(ww.message) for ww in w)) with warnings.catch_warnings(record=True) as w: # Warning for too short a filter filter_data(a, sfreq, 1, 8, filter_length='0.5s', fir_design='firwin2') assert_true(any('Increase filter_length' in str(ww.message) for ww in w)) # try new default and old default freqs = fftfreq(a.shape[-1], 1. / sfreq) A = np.abs(fft(a)) kwargs = dict(fir_design='firwin') for fl in ['auto', '10s', '5000ms', 1024, 1023]: bp = filter_data(a, sfreq, 4, 8, None, fl, 1.0, 1.0, **kwargs) bs = filter_data(a, sfreq, 8 + 1.0, 4 - 1.0, None, fl, 1.0, 1.0, **kwargs) lp = filter_data(a, sfreq, None, 8, None, fl, 10, 1.0, n_jobs=2, **kwargs) hp = filter_data(lp, sfreq, 4, None, None, fl, 1.0, 10, **kwargs) assert_allclose(hp, bp, rtol=1e-3, atol=1e-3) assert_allclose(bp + bs, a, rtol=1e-3, atol=1e-3) # Sanity check ttenuation mask = (freqs > 5.5) & (freqs < 6.5) assert_allclose(np.mean(np.abs(fft(bp)[:, mask]) / A[:, mask]), 1., atol=0.02) assert_allclose(np.mean(np.abs(fft(bs)[:, mask]) / A[:, mask]), 0., atol=0.2) # now the minimum-phase versions bp = filter_data(a, sfreq, 4, 8, None, fl, 1.0, 1.0, phase='minimum', **kwargs) bs = filter_data(a, sfreq, 8 + 1.0, 4 - 1.0, None, fl, 1.0, 1.0, phase='minimum', **kwargs) assert_allclose(np.mean(np.abs(fft(bp)[:, mask]) / A[:, mask]), 1., atol=0.11) assert_allclose(np.mean(np.abs(fft(bs)[:, mask]) / A[:, mask]), 0., atol=0.3) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp, 2 * bp.shape[-1], axis=-1, window='boxcar'), bp.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(sfreq * sig_len_secs))) / float(sfreq) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * sfreq / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='ba') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_equal(iir_params['a'].size - 1, 3) assert_equal(iir_params['b'].size - 1, 3) iir_params = dict(ftype='butter', order=4, output='ba') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_equal(iir_params['a'].size - 1, 4) assert_equal(iir_params['b'].size - 1, 4) iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='sos') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter, which requires 2 SOS ((2, 6)) assert_equal(iir_params['sos'].shape, (2, 6)) iir_params = dict(ftype='butter', order=4, output='sos') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_equal(iir_params['sos'].shape, (2, 6)) # check that picks work for 3d array with one channel and picks=[0] a = rng.randn(5 * sfreq, 5 * sfreq) b = a[:, None, :] a_filt = filter_data(a, sfreq, 4, 8, None, 400, 2.0, 2.0, fir_design='firwin') b_filt = filter_data(b, sfreq, 4, 8, [0], 400, 2.0, 2.0, fir_design='firwin') assert_array_equal(a_filt[:, None, :], b_filt) # check for n-dimensional case a = rng.randn(2, 2, 2, 2) with warnings.catch_warnings(record=True): # filter too long assert_raises(ValueError, filter_data, a, sfreq, 4, 8, np.array([0, 1]), 100, 1.0, 1.0)
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling """ sfreq = 500 sig_len_secs = 30 a = np.random.randn(2, sig_len_secs * sfreq) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, filter_length=fl) for nj in ['blah', 0.5]: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, n_jobs=nj) # > Nyq/2 assert_raises(ValueError, band_pass_filter, a, sfreq, 4, sfreq / 2.) assert_raises(ValueError, low_pass_filter, a, sfreq, sfreq / 2.) # check our short-filter warning: with warnings.catch_warnings(record=True) as w: # Warning for low attenuation band_pass_filter(a, sfreq, 1, 8, filter_length=1024) # Warning for too short a filter band_pass_filter(a, sfreq, 1, 8, filter_length='0.5s') assert_true(len(w) >= 2) # try new default and old default for fl in ['10s', '5000ms', None]: bp = band_pass_filter(a, sfreq, 4, 8, filter_length=fl) bs = band_stop_filter(a, sfreq, 4 - 0.5, 8 + 0.5, filter_length=fl) lp = low_pass_filter(a, sfreq, 8, filter_length=fl, n_jobs=2) hp = high_pass_filter(lp, sfreq, 4, filter_length=fl) assert_array_almost_equal(hp, bp, 2) assert_array_almost_equal(bp + bs, a, 1) # Overlap-add filtering with a fixed filter length filter_length = 8192 bp_oa = band_pass_filter(a, sfreq, 4, 8, filter_length) bs_oa = band_stop_filter(a, sfreq, 4 - 0.5, 8 + 0.5, filter_length) lp_oa = low_pass_filter(a, sfreq, 8, filter_length) hp_oa = high_pass_filter(lp_oa, sfreq, 4, filter_length) assert_array_almost_equal(hp_oa, bp_oa, 2) # Our filters are no longer quite complementary with linear rolloffs :( # this is the tradeoff for stability of the filtering # obtained by directly using the result of firwin2 instead of # modifying it... assert_array_almost_equal(bp_oa + bs_oa, a, 1) # The two methods should give the same result # As filtering for short signals uses a circular convolution (FFT) and # the overlap-add filter implements a linear convolution, the signal # boundary will be slightly different and we ignore it n_edge_ignore = 0 assert_array_almost_equal(hp[n_edge_ignore:-n_edge_ignore], hp_oa[n_edge_ignore:-n_edge_ignore], 2) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp_oa, 2 * bp_oa.shape[-1], axis=-1, window='boxcar'), bp_oa.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(sfreq * sig_len_secs))) / float(sfreq) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * sfreq / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20) iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_true(iir_params['a'].size - 1 == 3) assert_true(iir_params['b'].size - 1 == 3) iir_params = dict(ftype='butter', order=4) iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_true(iir_params['a'].size - 1 == 4) assert_true(iir_params['b'].size - 1 == 4) # check that picks work for 3d array with one channel and picks=[0] a = np.random.randn(5 * sfreq, 5 * sfreq) b = a[:, None, :] with warnings.catch_warnings(record=True) as w: a_filt = band_pass_filter(a, sfreq, 4, 8) b_filt = band_pass_filter(b, sfreq, 4, 8, picks=[0]) assert_array_equal(a_filt[:, None, :], b_filt) # check for n-dimensional case a = np.random.randn(2, 2, 2, 2) assert_raises(ValueError, band_pass_filter, a, sfreq, Fp1=4, Fp2=8, picks=np.array([0, 1])) # test that our overlap-add filtering doesn't introduce strange # artifacts (from mne_analyze mailing list 2015/06/25) N = 300 sfreq = 100. lp = 10. sine_freq = 1. x = np.ones(N) x += np.sin(2 * np.pi * sine_freq * np.arange(N) / sfreq) with warnings.catch_warnings(record=True): # filter attenuation x_filt = low_pass_filter(x, sfreq, lp, '1s') # the firwin2 function gets us this close assert_allclose(x, x_filt, rtol=1e-3, atol=1e-3)
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling""" sfreq = 500 sig_len_secs = 30 a = rng.randn(2, sig_len_secs * sfreq) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, fl, 1.0, 1.0, phase='zero') for nj in ['blah', 0.5]: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, 100, 1.0, 1.0, n_jobs=nj, phase='zero') # > Nyq/2 assert_raises(ValueError, band_pass_filter, a, sfreq, 4, sfreq / 2., 100, 1.0, 1.0, phase='zero') assert_raises(ValueError, low_pass_filter, a, sfreq, sfreq / 2., 100, 1.0, phase='zero') # check our short-filter warning: with warnings.catch_warnings(record=True) as w: # Warning for low attenuation band_pass_filter(a, sfreq, 1, 8, filter_length=1024, phase='zero') assert_true(any('attenuation' in str(ww.message) for ww in w)) with warnings.catch_warnings(record=True) as w: # Warning for too short a filter band_pass_filter(a, sfreq, 1, 8, filter_length='0.5s', phase='zero') assert_true(any('Increase filter_length' in str(ww.message) for ww in w)) # try new default and old default for fl in ['auto', '10s', '5000ms', 8192]: bp = band_pass_filter(a, sfreq, 4, 8, fl, 1.0, 1.0, phase='zero') bs = band_stop_filter(a, sfreq, 4 - 1.0, 8 + 1.0, fl, 1.0, 1.0, phase='zero') lp = low_pass_filter(a, sfreq, 8, fl, 1.0, n_jobs=2, phase='zero') hp = high_pass_filter(lp, sfreq, 4, fl, 1.0, phase='zero') assert_array_almost_equal(hp, bp, 5) assert_array_almost_equal(bp + bs, a, 5) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp, 2 * bp.shape[-1], axis=-1, window='boxcar'), bp.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(sfreq * sig_len_secs))) / float(sfreq) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * sfreq / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='ba') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_equal(iir_params['a'].size - 1, 3) assert_equal(iir_params['b'].size - 1, 3) iir_params = dict(ftype='butter', order=4, output='ba') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_equal(iir_params['a'].size - 1, 4) assert_equal(iir_params['b'].size - 1, 4) iir_params = dict(ftype='cheby1', gpass=1, gstop=20, output='sos') iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter, which requires 2 SOS ((2, 6)) assert_equal(iir_params['sos'].shape, (2, 6)) iir_params = dict(ftype='butter', order=4, output='sos') iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_equal(iir_params['sos'].shape, (2, 6)) # check that picks work for 3d array with one channel and picks=[0] a = rng.randn(5 * sfreq, 5 * sfreq) b = a[:, None, :] a_filt = band_pass_filter(a, sfreq, 4, 8, 1000, 2.0, 2.0, phase='zero') b_filt = band_pass_filter(b, sfreq, 4, 8, 1000, 2.0, 2.0, picks=[0], phase='zero') assert_array_equal(a_filt[:, None, :], b_filt) # check for n-dimensional case a = rng.randn(2, 2, 2, 2) with warnings.catch_warnings(record=True): # filter too long assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, 100, 1.0, 1.0, picks=np.array([0, 1]), phase='zero')
def test_filters(): """Test low-, band-, high-pass, and band-stop filters plus resampling """ sfreq = 500 sig_len_secs = 30 a = rng.randn(2, sig_len_secs * sfreq) # let's test our catchers for fl in ['blah', [0, 1], 1000.5, '10ss', '10']: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, filter_length=fl) for nj in ['blah', 0.5]: assert_raises(ValueError, band_pass_filter, a, sfreq, 4, 8, n_jobs=nj) # > Nyq/2 assert_raises(ValueError, band_pass_filter, a, sfreq, 4, sfreq / 2.) assert_raises(ValueError, low_pass_filter, a, sfreq, sfreq / 2.) # check our short-filter warning: with warnings.catch_warnings(record=True) as w: # Warning for low attenuation band_pass_filter(a, sfreq, 1, 8, filter_length=1024) # Warning for too short a filter band_pass_filter(a, sfreq, 1, 8, filter_length='0.5s') assert_true(len(w) >= 2) # try new default and old default for fl in ['10s', '5000ms', None]: bp = band_pass_filter(a, sfreq, 4, 8, filter_length=fl) bs = band_stop_filter(a, sfreq, 4 - 0.5, 8 + 0.5, filter_length=fl) lp = low_pass_filter(a, sfreq, 8, filter_length=fl, n_jobs=2) hp = high_pass_filter(lp, sfreq, 4, filter_length=fl) assert_array_almost_equal(hp, bp, 2) assert_array_almost_equal(bp + bs, a, 1) # Overlap-add filtering with a fixed filter length filter_length = 8192 bp_oa = band_pass_filter(a, sfreq, 4, 8, filter_length) bs_oa = band_stop_filter(a, sfreq, 4 - 0.5, 8 + 0.5, filter_length) lp_oa = low_pass_filter(a, sfreq, 8, filter_length) hp_oa = high_pass_filter(lp_oa, sfreq, 4, filter_length) assert_array_almost_equal(hp_oa, bp_oa, 2) # Our filters are no longer quite complementary with linear rolloffs :( # this is the tradeoff for stability of the filtering # obtained by directly using the result of firwin2 instead of # modifying it... assert_array_almost_equal(bp_oa + bs_oa, a, 1) # The two methods should give the same result # As filtering for short signals uses a circular convolution (FFT) and # the overlap-add filter implements a linear convolution, the signal # boundary will be slightly different and we ignore it n_edge_ignore = 0 assert_array_almost_equal(hp[n_edge_ignore:-n_edge_ignore], hp_oa[n_edge_ignore:-n_edge_ignore], 2) # and since these are low-passed, downsampling/upsampling should be close n_resamp_ignore = 10 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs=2), 1, 2, n_jobs=2) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # note that on systems without CUDA, this line serves as a test for a # graceful fallback to n_jobs=1 bp_up_dn = resample(resample(bp_oa, 2, 1, n_jobs='cuda'), 1, 2, n_jobs='cuda') assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # test to make sure our resamling matches scipy's bp_up_dn = sp_resample(sp_resample(bp_oa, 2 * bp_oa.shape[-1], axis=-1, window='boxcar'), bp_oa.shape[-1], window='boxcar', axis=-1) assert_array_almost_equal(bp_oa[n_resamp_ignore:-n_resamp_ignore], bp_up_dn[n_resamp_ignore:-n_resamp_ignore], 2) # make sure we don't alias t = np.array(list(range(sfreq * sig_len_secs))) / float(sfreq) # make sinusoid close to the Nyquist frequency sig = np.sin(2 * np.pi * sfreq / 2.2 * t) # signal should disappear with 2x downsampling sig_gone = resample(sig, 1, 2)[n_resamp_ignore:-n_resamp_ignore] assert_array_almost_equal(np.zeros_like(sig_gone), sig_gone, 2) # let's construct some filters iir_params = dict(ftype='cheby1', gpass=1, gstop=20) iir_params = construct_iir_filter(iir_params, 40, 80, 1000, 'low') # this should be a third order filter assert_true(iir_params['a'].size - 1 == 3) assert_true(iir_params['b'].size - 1 == 3) iir_params = dict(ftype='butter', order=4) iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low') assert_true(iir_params['a'].size - 1 == 4) assert_true(iir_params['b'].size - 1 == 4) # check that picks work for 3d array with one channel and picks=[0] a = rng.randn(5 * sfreq, 5 * sfreq) b = a[:, None, :] with warnings.catch_warnings(record=True) as w: a_filt = band_pass_filter(a, sfreq, 4, 8) b_filt = band_pass_filter(b, sfreq, 4, 8, picks=[0]) assert_array_equal(a_filt[:, None, :], b_filt) # check for n-dimensional case a = rng.randn(2, 2, 2, 2) assert_raises(ValueError, band_pass_filter, a, sfreq, Fp1=4, Fp2=8, picks=np.array([0, 1])) # test that our overlap-add filtering doesn't introduce strange # artifacts (from mne_analyze mailing list 2015/06/25) N = 300 sfreq = 100. lp = 10. sine_freq = 1. x = np.ones(N) x += np.sin(2 * np.pi * sine_freq * np.arange(N) / sfreq) with warnings.catch_warnings(record=True): # filter attenuation x_filt = low_pass_filter(x, sfreq, lp, '1s') # the firwin2 function gets us this close assert_allclose(x, x_filt, rtol=1e-3, atol=1e-3)