# This filter hypothetically achieves zero ripple in the frequency domain,
# perfect attenuation, and perfect steepness. However, due to the discontunity
# in the frequency response, the filter would require infinite ringing in the
# time domain (i.e., infinite order) to be realized. Another way to think of
# this is that a rectangular window in frequency is actually sinc_ function
# in time, which requires an infinite number of samples, and thus infinite
# time, to represent. So although this filter has ideal frequency suppression,
# it has poor time-domain characteristics.
#
# Let's try to naïvely make a brick-wall filter of length 0.1 sec, and look
# at the filter itself in the time domain and the frequency domain:

n = int(round(0.1 * sfreq)) + 1
t = np.arange(-n // 2, n // 2) / sfreq  # center our sinc
h = np.sinc(2 * f_p * t) / (4 * np.pi)
plot_filter(h, sfreq, freq, gain, 'Sinc (0.1 sec)', flim=flim)

###############################################################################
# This is not so good! Making the filter 10 times longer (1 sec) gets us a
# bit better stop-band suppression, but still has a lot of ringing in
# the time domain. Note the x-axis is an order of magnitude longer here,
# and the filter has a correspondingly much longer group delay (again equal
# to half the filter length, or 0.5 seconds):

n = int(round(1. * sfreq)) + 1
t = np.arange(-n // 2, n // 2) / sfreq
h = np.sinc(2 * f_p * t) / (4 * np.pi)
plot_filter(h, sfreq, freq, gain, 'Sinc (1.0 sec)', flim=flim)

###############################################################################
# Let's make the stop-band tighter still with a longer filter (10 sec),
Ejemplo n.º 2
0
# This filter hypothetically achieves zero ripple in the frequency domain,
# perfect attenuation, and perfect steepness. However, due to the discontunity
# in the frequency response, the filter would require infinite ringing in the
# time domain (i.e., infinite order) to be realized. Another way to think of
# this is that a rectangular window in frequency is actually sinc_ function
# in time, which requires an infinite number of samples, and thus infinite
# time, to represent. So although this filter has ideal frequency suppression,
# it has poor time-domain characteristics.
#
# Let's try to naïvely make a brick-wall filter of length 0.1 sec, and look
# at the filter itself in the time domain and the frequency domain:

n = int(round(0.1 * sfreq)) + 1
t = np.arange(-n // 2, n // 2) / sfreq  # center our sinc
h = np.sinc(2 * f_p * t) / (4 * np.pi)
plot_filter(h, sfreq, freq, gain, 'Sinc (0.1 sec)', flim=flim)

###############################################################################
# This is not so good! Making the filter 10 times longer (1 sec) gets us a
# bit better stop-band suppression, but still has a lot of ringing in
# the time domain. Note the x-axis is an order of magnitude longer here,
# and the filter has a correspondingly much longer group delay (again equal
# to half the filter length, or 0.5 seconds):

n = int(round(1. * sfreq)) + 1
t = np.arange(-n // 2, n // 2) / sfreq
h = np.sinc(2 * f_p * t) / (4 * np.pi)
plot_filter(h, sfreq, freq, gain, 'Sinc (1.0 sec)', flim=flim)

###############################################################################
# Let's make the stop-band tighter still with a longer filter (10 sec),
Ejemplo n.º 3
0
def test_plot_filter():
    """Test filter plotting."""
    l_freq, h_freq, sfreq = 2., 40., 1000.
    data = np.zeros(5000)
    freq = [0, 2, 40, 50, 500]
    gain = [0, 1, 1, 0, 0]
    h = create_filter(data, sfreq, l_freq, h_freq, fir_design='firwin2')
    plot_filter(h, sfreq)
    plt.close('all')
    plot_filter(h, sfreq, freq, gain)
    plt.close('all')
    iir = create_filter(data, sfreq, l_freq, h_freq, method='iir')
    plot_filter(iir, sfreq)
    plt.close('all')
    plot_filter(iir, sfreq, freq, gain)
    plt.close('all')
    iir_ba = create_filter(data,
                           sfreq,
                           l_freq,
                           h_freq,
                           method='iir',
                           iir_params=dict(output='ba'))
    plot_filter(iir_ba, sfreq, freq, gain)
    plt.close('all')
    plot_filter(h, sfreq, freq, gain, fscale='linear')
    plt.close('all')
# in the frequency response, the filter would require infinite ringing in the
# time domain (i.e., infinite order) to be realized. Another way to think of
# this is that a rectangular window in the frequency domain is actually a sinc_
# function in the time domain, which requires an infinite number of samples
# (and thus infinite time) to represent. So although this filter has ideal
# frequency suppression, it has poor time-domain characteristics.
#
# Let's try to naïvely make a brick-wall (sinc) filter of length 0.1 s, and
# look at the filter itself in the time domain and the frequency domain:

n = int(round(0.1 * sfreq))
n -= n % 2 - 1  # make it odd
t = np.arange(-(n // 2), n // 2 + 1) / sfreq  # center our sinc
h = np.sinc(2 * f_p * t) / (4 * np.pi)
kwargs = dict(flim=flim, dlim=dlim)
plot_filter(h, sfreq, freq, gain, 'Sinc (0.1 s)', compensate=True, **kwargs)

# %%
# This is not so good! Making the filter 10 times longer (1 s) gets us a
# slightly better stop-band suppression, but still has a lot of ringing in
# the time domain. Note the x-axis is an order of magnitude longer here,
# and the filter has a correspondingly much longer group delay (again equal
# to half the filter length, or 0.5 seconds):

n = int(round(1. * sfreq))
n -= n % 2 - 1  # make it odd
t = np.arange(-(n // 2), n // 2 + 1) / sfreq
h = np.sinc(2 * f_p * t) / (4 * np.pi)
plot_filter(h, sfreq, freq, gain, 'Sinc (1.0 s)', compensate=True, **kwargs)

# %%
Ejemplo n.º 5
0
    def learn_filters(self, fs, log_approx_levels=4):
        """Learn digital filters that approximate the Gaussian peaks and invert the background"""
        from scipy.signal import cheby1, remez
        from mne.viz import plot_filter

        nyquist = fs / 2

        log_filter_coeffs, gaussian_filter_coeffs = [], []
        log_amplitudes, gaussian_amplitudes = [], []

        ideal_gains, figs = [], []

        frequencies = np.linspace(0, nyquist, 10000)

        if self.background_mode == 'knee':
            slope = self.background_params_[2]
            knee = self.background_params_[1]
        else:
            slope = self.background_params_[1]
            knee = 0.

        if knee < 0.:
            knee = 0.

        offset = self.background_params_[0]

        print('slope, knee, offset:')
        print(slope, knee, offset)

        logarg = knee + frequencies**slope
        logarg[logarg < 0] = 1e-20

        ideal_gain = np.log10(logarg)
        ideal_gain = ideal_gain / np.max(ideal_gain)
        ideal_gain[0] = 0
        ideal_gain = np.clip(ideal_gain, 1e-20, 1)

        print('ideal_gain', np.min(ideal_gain), np.max(ideal_gain))

        ideal_gains.append(ideal_gain)

        print('Cutoffs/ripple for log approximation:')
        for i in range(log_approx_levels):
            L_half = 1 - (1 / (2**(i + 1)))  # Half of remaining Log amplitude
            f_half = ((knee + nyquist**slope)**L_half - knee)**(
                1 / slope)  # Frequency of half of remaining log amp

            max_ripple = 0.4 * np.sqrt((2**i) * 4 * slope)

            print('L, f_half, max_ripple', L_half, f_half, max_ripple)

            b, a = cheby1(1, max_ripple, f_half, btype='highpass', fs=fs)

            coeffs = tuple((b, a))

            log_filter_coeffs.append(coeffs)
            log_amplitudes.append(1 - L_half)

            iir_params = dict(b=b, a=a)

            f = plot_filter(iir_params,
                            fs,
                            freq=frequencies,
                            gain=ideal_gain,
                            color='#1f77b4',
                            flim=[0, 40],
                            fscale='linear',
                            alim=(-30, 10),
                            show=False)
            f.set_figwidth(6)
            f.set_figheight(12)
            figs.append(f)

        print('Gaussian approximations:')
        # bandpass each of the peaks
        for idx, ([centre_frequency, amplitude,
                   std_dev]) in enumerate(self._gaussian_params):
            ideal_gain = ((1 / (std_dev * np.sqrt(2 * np.pi))) *
                          np.exp(-(1 / 2) * ((
                              (frequencies - centre_frequency) / std_dev)**2)))
            ideal_gain = ((ideal_gain - np.min(ideal_gain)) /
                          (np.max(ideal_gain) - np.min(ideal_gain)))
            ideal_gain = np.clip(ideal_gain, 1e-20, 1)

            # wp = np.sqrt((np.ln(0.5) + np.ln(std_dev) + np.ln(np.sqrt(2*np.pi))))*std_dev

            wp = 1 / (np.sqrt(
                np.log(0.25 * np.pi * std_dev**2) * (std_dev**2)))
            # ws = np.sqrt(-(np.log(0.001) + np.log(std_dev) + np.log(np.sqrt(2*np.pi))))*std_dev

            wp_low = (centre_frequency - wp)
            wp_high = (centre_frequency + wp)

            ws_low = (centre_frequency - 3 * std_dev)
            ws_high = (centre_frequency + 3 * std_dev)

            if ws_low < 0:
                ws_low = 0.1

            if ws_high > nyquist:
                ws_high = nyquist

            print(ws_low, wp_low, wp_high, ws_high)

            result = None
            counter = 0
            while result is None:
                try:
                    ws_low = centre_frequency - 3 * std_dev + (counter / 10 *
                                                               std_dev)
                    ws_high = centre_frequency + 3 * std_dev - (counter / 10 *
                                                                std_dev)

                    wp_low = centre_frequency - wp - (counter / 10 * std_dev)
                    wp_high = centre_frequency + wp + (counter / 10 * std_dev)

                    if counter > 100:
                        result = 1
                        print(
                            'Could not fit a digital filter to this Gaussian')

                    b = remez(256,
                              [0, ws_low, wp_low, wp_high, ws_high, nyquist],
                              [0, 1, 0],
                              fs=fs)

                    result = 1
                except:
                    counter += 1
                    print('Transition band too wide! Relaxing the math...',
                          counter)

            gaussian_filter_coeffs.append(b)
            gaussian_amplitudes.append(amplitude)

            ideal_gains.append(ideal_gain)

            f = plot_filter(b,
                            fs,
                            freq=frequencies,
                            gain=ideal_gain,
                            color='#1f77b4',
                            flim=[0, 40],
                            fscale='linear',
                            alim=(-60, 10),
                            show=False)
            f.set_figwidth(6)
            f.set_figheight(12)
            figs.append(f)

        return log_filter_coeffs, gaussian_filter_coeffs, log_amplitudes, gaussian_amplitudes, figs, ideal_gains, offset
Ejemplo n.º 6
0
def test_plot_filter():
    """Test filter plotting."""
    l_freq, h_freq, sfreq = 2., 40., 1000.
    data = np.zeros(5000)
    freq = [0, 2, 40, 50, 500]
    gain = [0, 1, 1, 0, 0]
    h = create_filter(data, sfreq, l_freq, h_freq, fir_design='firwin2')
    plot_filter(h, sfreq)
    plt.close('all')
    plot_filter(h, sfreq, freq, gain)
    plt.close('all')
    iir = create_filter(data, sfreq, l_freq, h_freq, method='iir')
    plot_filter(iir, sfreq)
    plt.close('all')
    plot_filter(iir, sfreq, freq, gain)
    plt.close('all')
    iir_ba = create_filter(data, sfreq, l_freq, h_freq, method='iir',
                           iir_params=dict(output='ba'))
    plot_filter(iir_ba, sfreq, freq, gain)
    plt.close('all')
    fig = plot_filter(h, sfreq, freq, gain, fscale='linear')
    assert len(fig.axes) == 3
    plt.close('all')
    fig = plot_filter(h, sfreq, freq, gain, fscale='linear',
                      plot=('time', 'delay'))
    assert len(fig.axes) == 2
    plt.close('all')
    fig = plot_filter(h, sfreq, freq, gain, fscale='linear',
                      plot=['magnitude', 'delay'])
    assert len(fig.axes) == 2
    plt.close('all')
    fig = plot_filter(h, sfreq, freq, gain, fscale='linear',
                      plot='magnitude')
    assert len(fig.axes) == 1
    plt.close('all')
    fig = plot_filter(h, sfreq, freq, gain, fscale='linear',
                      plot=('magnitude'))
    assert len(fig.axes) == 1
    plt.close('all')
    with pytest.raises(ValueError, match='Invalid value for the .plot'):
        plot_filter(h, sfreq, freq, gain, plot=('turtles'))
    _, axes = plt.subplots(1)
    fig = plot_filter(h, sfreq, freq, gain, plot=('magnitude'), axes=axes)
    assert len(fig.axes) == 1
    _, axes = plt.subplots(2)
    fig = plot_filter(h, sfreq, freq, gain, plot=('magnitude', 'delay'),
                      axes=axes)
    assert len(fig.axes) == 2
    plt.close('all')
    _, axes = plt.subplots(1)
    with pytest.raises(ValueError, match='Length of axes'):
        plot_filter(h, sfreq, freq, gain,
                    plot=('magnitude', 'delay'), axes=axes)
Ejemplo n.º 7
0
def test_plot_filter():
    """Test filter plotting."""
    import matplotlib.pyplot as plt
    l_freq, h_freq, sfreq = 2., 40., 1000.
    data = np.zeros(5000)
    freq = [0, 2, 40, 50, 500]
    gain = [0, 1, 1, 0, 0]
    h = create_filter(data, sfreq, l_freq, h_freq)
    plot_filter(h, sfreq)
    plt.close('all')
    plot_filter(h, sfreq, freq, gain)
    plt.close('all')
    iir = create_filter(data, sfreq, l_freq, h_freq, method='iir')
    plot_filter(iir, sfreq)
    plt.close('all')
    plot_filter(iir, sfreq,  freq, gain)
    plt.close('all')
    iir_ba = create_filter(data, sfreq, l_freq, h_freq, method='iir',
                           iir_params=dict(output='ba'))
    plot_filter(iir_ba, sfreq,  freq, gain)
    plt.close('all')
    plot_filter(h, sfreq, freq, gain, fscale='linear')
    plt.close('all')
Ejemplo n.º 8
0
fpath = subject.dataset_path(proc=proc, suffix=suffix, ext=ext)
raw = mne.io.read_raw_fif(fpath, preload=True)
X = raw.get_data()
#%% Filter properties

h = mne.filter.create_filter(X,
                             sfreq=sfreq,
                             l_freq=l_freq,
                             h_freq=h_freq,
                             filter_length='auto',
                             l_trans_bandwidth=l_trans_bandwidth,
                             h_trans_bandwidth=h_trans_bandwidth,
                             fir_window=fir_window,
                             phase=phase)

plot_filter(h, sfreq=500)

#%% Extract events time stamp of 2 sitmulus presentation (Place and Face)

events = mne.events_from_annotations(raw)
events_sample_stamp = events[0][:, 0]
events_time_stamp = events_sample_stamp / sfreq

#%% Envelope of a representative visual channel during 2 stimulus

raw_band = raw.copy().pick_channels(['LTo6']).filter(
    l_freq=l_freq,
    h_freq=l_freq + band_size,
    phase=phase,
    filter_length='auto',
    l_trans_bandwidth=l_trans_bandwidth,