Esempio n. 1
0
def test_plot_frequency_response():

    coefs = design_fir_filter(FS, 'bandpass', (8, 12), 3)
    f_db, db = compute_frequency_response(coefs, a_vals=1, fs=FS)

    plot_frequency_response(f_db, db,
                            save_fig=True, file_path=TEST_PLOTS_PATH,
                            file_name='test_plot_frequency_response.png')
Esempio n. 2
0
def test_plot_frequency_response():

    coefs = design_fir_filter(2000, 1000, 'bandpass', (8, 12), 3)
    f_db, db = compute_frequency_response(coefs, a_vals=1, fs=1000)

    plot_frequency_response(f_db, db)

    assert True
Esempio n. 3
0
def test_plot_filter_properties():

    fs = 1000
    coefs = design_fir_filter(2000, fs, 'bandpass', (8, 12), 3)
    f_db, db = compute_frequency_response(coefs, a_vals=1, fs=1000)

    plot_filter_properties(f_db, db, fs, coefs)

    assert True
Esempio n. 4
0
def filter_signal_iir(sig,
                      fs,
                      pass_type,
                      f_range,
                      butterworth_order,
                      print_transitions=False,
                      plot_properties=False,
                      return_filter=False):
    """Apply an IIR filter to a signal.

    Parameters
    ----------
    sig : array
        Time series to be filtered.
    fs : float
        Sampling rate, in Hz.
    pass_type : {'bandpass', 'bandstop', 'lowpass', 'highpass'}
        Which kind of filter to apply:

        * 'bandpass': apply a bandpass filter
        * 'bandstop': apply a bandstop (notch) filter
        * 'lowpass': apply a lowpass filter
        * 'highpass' : apply a highpass filter
    f_range : tuple of (float, float) or float
        Cutoff frequency(ies) used for filter, specified as f_lo & f_hi.
        For 'bandpass' & 'bandstop', must be a tuple.
        For 'lowpass' or 'highpass', can be a float that specifies pass frequency, or can be
        a tuple and is assumed to be (None, f_hi) for 'lowpass', and (f_lo, None) for 'highpass'.
    butterworth_order : int
        Order of the butterworth filter, if using an IIR filter.
        See input 'N' in scipy.signal.butter.
    print_transitions : bool, optional, default: False
        If True, print out the transition and pass bandwidths.
    plot_properties : bool, optional, default: False
        If True, plot the properties of the filter, including frequency response and/or kernel.
    return_filter : bool, optional, default: False
        If True, return the filter coefficients of the IIR filter.

    Returns
    -------
    sig_filt : 1d array
        Filtered time series.
    filter_coefs : tuple of (1d array, 1d array)
        Filter coefficients of the IIR filter, as (b_vals, a_vals).
        Only returned if `return_filter` is True.
    """

    # Design filter
    b_vals, a_vals = design_iir_filter(fs, pass_type, f_range,
                                       butterworth_order)

    # Check filter properties: compute transition bandwidth & run checks
    check_filter_properties(b_vals,
                            a_vals,
                            fs,
                            pass_type,
                            f_range,
                            verbose=print_transitions)

    # Remove any NaN on the edges of 'sig'
    sig, sig_nans = remove_nans(sig)

    # Apply filter
    sig_filt = apply_iir_filter(sig, b_vals, a_vals)

    # Add NaN back on the edges of 'sig', if there were any at the beginning
    sig_filt = restore_nans(sig_filt, sig_nans)

    # Plot frequency response, if desired
    if plot_properties:
        f_db, db = compute_frequency_response(b_vals, a_vals, fs)
        plot_frequency_response(f_db, db)

    if return_filter:
        return sig_filt, (b_vals, a_vals)
    else:
        return sig_filt
Esempio n. 5
0
def check_filter_properties(b_vals, a_vals, fs, pass_type, f_range, transitions=(-20, -3), verbose=True):
    """Check a filters properties, including pass band and transition band.

    Parameters
    ----------
    b_vals : 1d array
        B value filter coefficients for a filter.
    a_vals : 1d array
        A value filter coefficients for a filter.
    fs : float
        Sampling rate, in Hz.
    pass_type : {'bandpass', 'bandstop', 'lowpass', 'highpass'}
        Which kind of filter to apply:

        * 'bandpass': apply a bandpass filter
        * 'bandstop': apply a bandstop (notch) filter
        * 'lowpass': apply a lowpass filter
        * 'highpass' : apply a highpass filter
    f_range : tuple of (float, float) or float
        Cutoff frequency(ies) used for filter, specified as f_lo & f_hi.
        For 'bandpass' & 'bandstop', must be a tuple.
        For 'lowpass' or 'highpass', can be a float that specifies pass frequency, or can be
        a tuple and is assumed to be (None, f_hi) for 'lowpass', and (f_lo, None) for 'highpass'.
    transitions : tuple of (float, float), optional, default: (-20, -3)
        Cutoffs, in dB, that define the transition band.
    verbose : bool, optional, default: True
        Whether to print out transition and pass bands.

    Returns
    -------
    passes : bool
        Whether all the checks pass. False if one or more checks fail.
    """

    # Import utility functions inside function to avoid circular imports
    from neurodsp.filt.utils import (compute_frequency_response,
                                     compute_pass_band, compute_transition_band)

    # Initialize variable to keep track if all checks pass
    passes = True

    # Compute the frequency response
    f_db, db = compute_frequency_response(b_vals, a_vals, fs)

    # Check that frequency response goes below transition level (has significant attenuation)
    if np.min(db) >= transitions[0]:
        passes = False
        warn('The filter attenuation never goes below {} dB.'\
             'Increase filter length.'.format(transitions[0]))
        # If there is no attenuation, cannot calculate bands, so return here
        return passes

    # Check that both sides of a bandpass have significant attenuation
    if pass_type == 'bandpass':
        if db[0] >= transitions[0] or db[-1] >= transitions[0]:
            passes = False
            warn('The low or high frequency stopband never gets attenuated by'\
                 'more than {} dB. Increase filter length.'.format(abs(transitions[0])))

    # Compute pass & transition bandwidth
    pass_bw = compute_pass_band(fs, pass_type, f_range)
    transition_bw = compute_transition_band(f_db, db, transitions[0], transitions[1])

    # Raise warning if transition bandwidth is too high
    if transition_bw > pass_bw:
        passes = False
        warn('Transition bandwidth is  {:.1f}  Hz. This is greater than the desired'\
             'pass/stop bandwidth of  {:.1f} Hz'.format(transition_bw, pass_bw))

    # Print out transition bandwidth and pass bandwidth to the user
    if verbose:
        print('Transition bandwidth is {:.1f} Hz.'.format(transition_bw))
        print('Pass/stop bandwidth is {:.1f} Hz.'.format(pass_bw))

    return passes
Esempio n. 6
0
def test_plot_frequency_response():

    coefs = design_fir_filter(FS, 'bandpass', (8, 12), 3)
    f_db, db = compute_frequency_response(coefs, a_vals=1, fs=FS)

    plot_frequency_response(f_db, db)
Esempio n. 7
0
def filter_signal_fir(sig, fs, pass_type, f_range, n_cycles=3, n_seconds=None, remove_edges=True,
                      print_transitions=False, plot_properties=False, return_filter=False):
    """Apply an FIR filter to a signal.

    Parameters
    ----------
    sig : array
        Time series to be filtered.
    fs : float
        Sampling rate, in Hz.
    pass_type : {'bandpass', 'bandstop', 'lowpass', 'highpass'}
        Which kind of filter to apply:

        * 'bandpass': apply a bandpass filter
        * 'bandstop': apply a bandstop (notch) filter
        * 'lowpass': apply a lowpass filter
        * 'highpass' : apply a highpass filter
    f_range : tuple of (float, float) or float
        Cutoff frequency(ies) used for filter, specified as f_lo & f_hi.
        For 'bandpass' & 'bandstop', must be a tuple.
        For 'lowpass' or 'highpass', can be a float that specifies pass frequency, or can be
        a tuple and is assumed to be (None, f_hi) for 'lowpass', and (f_lo, None) for 'highpass'.
    n_cycles : float, optional, default: 3
        Length of filter, in number of cycles, defined at the 'f_lo' frequency.
        This parameter is overwritten by `n_seconds`, if provided.
    n_seconds : float, optional
        Length of filter, in seconds. This parameter overwrites `n_cycles`.
    remove_edges : bool, optional
        If True, replace samples within half the kernel length to be np.nan.
    print_transitions : bool, optional, default: False
        If True, print out the transition and pass bandwidths.
    plot_properties : bool, optional, default: False
        If True, plot the properties of the filter, including frequency response and/or kernel.
    return_filter : bool, optional, default: False
        If True, return the filter coefficients of the FIR filter.

    Returns
    -------
    sig_filt : array
        Filtered time series.
    filter_coefs : 1d array
        Filter coefficients of the FIR filter. Only returned if `return_filter` is True.

    Examples
    --------
    Apply a band pass FIR filter to a simulated signal:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> filt_sig = filter_signal_fir(sig, fs=500, pass_type='bandpass', f_range=(1, 25))

    Apply a high pass FIR filter to a signal, with a specified number of cycles:

    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> filt_sig = filter_signal_fir(sig, fs=500, pass_type='highpass', f_range=(2, None), n_cycles=5)
    """

    # Design filter & check that the length is okay with signal
    filter_coefs = design_fir_filter(fs, pass_type, f_range, n_cycles, n_seconds)
    check_filter_length(sig.shape[-1], len(filter_coefs))

    # Check filter properties: compute transition bandwidth & run checks
    check_filter_properties(filter_coefs, 1, fs, pass_type, f_range, verbose=print_transitions)

    # Remove any NaN on the edges of 'sig'
    sig, sig_nans = remove_nans(sig)

    # Apply filter
    sig_filt = apply_fir_filter(sig, filter_coefs)

    # Remove edge artifacts
    if remove_edges:
        sig_filt = remove_filter_edges(sig_filt, len(filter_coefs))

    # Add NaN back on the edges of 'sig', if there were any at the beginning
    sig_filt = restore_nans(sig_filt, sig_nans)

    # Plot filter properties, if specified
    if plot_properties:
        f_db, db = compute_frequency_response(filter_coefs, 1, fs)
        plot_filter_properties(f_db, db, fs, filter_coefs)

    if return_filter:
        return sig_filt, filter_coefs
    else:
        return sig_filt
Esempio n. 8
0
def filter_signal_iir(sig,
                      fs,
                      pass_type,
                      f_range,
                      butterworth_order,
                      print_transitions=False,
                      plot_properties=False,
                      return_filter=False):
    """Apply an IIR filter to a signal.

    Parameters
    ----------
    sig : array
        Time series to be filtered.
    fs : float
        Sampling rate, in Hz.
    pass_type : {'bandpass', 'bandstop', 'lowpass', 'highpass'}
        Which kind of filter to apply:

        * 'bandpass': apply a bandpass filter
        * 'bandstop': apply a bandstop (notch) filter
        * 'lowpass': apply a lowpass filter
        * 'highpass' : apply a highpass filter
    f_range : tuple of (float, float) or float
        Cutoff frequency(ies) used for filter, specified as f_lo & f_hi.
        For 'bandpass' & 'bandstop', must be a tuple.
        For 'lowpass' or 'highpass', can be a float that specifies pass frequency, or can be
        a tuple and is assumed to be (None, f_hi) for 'lowpass', and (f_lo, None) for 'highpass'.
    butterworth_order : int
        Order of the butterworth filter, if using an IIR filter.
        See input 'N' in scipy.signal.butter.
    print_transitions : bool, optional, default: False
        If True, print out the transition and pass bandwidths.
    plot_properties : bool, optional, default: False
        If True, plot the properties of the filter, including frequency response and/or kernel.
    return_filter : bool, optional, default: False
        If True, return the second order series coefficients of the IIR filter.

    Returns
    -------
    sig_filt : 1d array
        Filtered time series.
    sos : 2d array
        Second order series coefficients of the IIR filter. Has shape of (n_sections, 6).
        Only returned if `return_filter` is True.

    Examples
    --------
    Apply a bandstop IIR filter to a simulated signal:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> filt_sig = filter_signal_iir(sig, fs=500, pass_type='bandstop',
    ...                              f_range=(55, 65), butterworth_order=7)
    """

    # Design filter
    sos = design_iir_filter(fs, pass_type, f_range, butterworth_order)

    # Check filter properties: compute transition bandwidth & run checks
    check_filter_properties(sos,
                            None,
                            fs,
                            pass_type,
                            f_range,
                            verbose=print_transitions)

    # Remove any NaN on the edges of 'sig'
    sig, sig_nans = remove_nans(sig)

    # Apply filter
    sig_filt = apply_iir_filter(sig, sos)

    # Add NaN back on the edges of 'sig', if there were any at the beginning
    sig_filt = restore_nans(sig_filt, sig_nans)

    # Plot frequency response, if desired
    if plot_properties:
        f_db, db = compute_frequency_response(sos, None, fs)
        plot_frequency_response(f_db, db)

    if return_filter:
        return sig_filt, sos
    else:
        return sig_filt
Esempio n. 9
0
butterworth_order = 12

# Design the filter, getting the second-order series (sos) values for the filter
sos = design_iir_filter(fs, pass_type, f_range, butterworth_order)

###################################################################################################
#
# Now that we have our filter definition, we can evaluate our filter.
#
# Next, we can calculate the frequency response, :math:`b_k`, for our IIR filter.
#

###################################################################################################

# Compute the frequency response for the IIR filter
f_db, db = compute_frequency_response(sos, None, fs)

# Plot the frequency response
plot_frequency_response(f_db, db)

###################################################################################################
#
# Above, we can see our frequency response of our filter, which shows us how different
# frequencies are affected by our filter. Ideally, we want zero attenuation in our passband,
# and a lot of attenuation in the stopband(s).
#
# Another way to quantify these properties is the transition band, which is bandwidth (in Hz)
# that it takes for the filter to change from high to low attenuation. This quantifies how
# sharp the transition is between stopband and passband. By default, transition bands are computed
# as the range between -20 dB and -3 dB attenuation, but you can also customize these values.
#
Esempio n. 10
0
n_cycles = 3

# Design the filter coefficients for a specified filter
filter_coefs = design_fir_filter(fs, pass_type, f_range, n_cycles=n_cycles)

###################################################################################################
#
# Now that we have our filter coefficients, we can evaluate our filter.
#
# Next, we can calculate the frequency response, :math:`b_k`, for our alpha bandpass filter.
#

###################################################################################################

# Compute the frequency response of the filter
f_db, db = compute_frequency_response(filter_coefs, 1, fs)

# Plot the filter properties
plot_filter_properties(f_db, db, fs, filter_coefs)

###################################################################################################
#
# On the right is the impulse response, or the filter kernel. This is a visualization of our
# filter coefficients, which also demonstrates the activity of our filter for a single point
# (the impulse response).
#
# On the left, we can see the frequency response of our filter, which shows us how different
# frequencies are affected by our filter. Ideally, we want zero attenuation in our passband,
# and a lot of attenuation in the stopband(s).
#
# Another way to quantify these properties is the transition band, which is bandwidth (in Hz)