Exemplo n.º 1
0
def test_bandpass(fc_sigerr):
    """Test bandpass filter."""
    fc = fc_sigerr[0]
    sig_err = fc_sigerr[1]

    # Load signal
    signal = np.load(DATA_PATH + 'sim_bursting.npy')
    if sig_err:
        signal = signal[:5]

    Fs = 1000

    # Test output same length as input
    N_seconds = 0.5
    signal_filt = filt.bandpass_filter(signal, Fs, fc, N_seconds=N_seconds)
    assert len(signal) == len(signal_filt)

    # Test edge artifacts removed appropriately
    N_samples_filter = int(np.ceil(Fs * N_seconds))
    if N_samples_filter % 2 == 0:
        N_samples_filter = int(N_samples_filter + 1)
    N_samples_NaN = int(np.ceil(N_samples_filter / 2))
    assert np.all(np.isnan(signal_filt[:N_samples_NaN]))
    assert np.all(np.isnan(signal_filt[-N_samples_NaN:]))
    assert np.all(
        np.logical_not(np.isnan(signal_filt[N_samples_NaN:-N_samples_NaN])))

    # Test edge artifacts are not removed if desired
    signal_filt = filt.bandpass_filter(signal,
                                       Fs,
                                       fc,
                                       N_seconds=N_seconds,
                                       remove_edge_artifacts=False,
                                       plot_frequency_response=True,
                                       print_transition_band=True)
    assert np.all(np.logical_not(np.isnan(signal_filt)))

    # Test returns kernel and signal
    out = filt.bandpass_filter(signal,
                               Fs,
                               fc,
                               N_seconds=N_seconds,
                               return_kernel=True)
    assert len(out) == 2

    # Test same result if N_cycle and N_seconds used
    filt1 = filt.bandpass_filter(signal,
                                 Fs,
                                 fc,
                                 N_seconds=1,
                                 remove_edge_artifacts=False)
    filt2 = filt.bandpass_filter(signal,
                                 Fs,
                                 fc,
                                 N_cycles=8,
                                 remove_edge_artifacts=False)
    np.testing.assert_allclose(filt1, filt2)
Exemplo n.º 2
0
def test_amp():
    """Test phase time series functionality"""

    # Load signal
    signal = np.load(data_path + 'sim_bursting.npy')
    Fs = 1000  # Sampling rate
    f_range = (6, 14)  # Frequency range

    # Test output same length as input
    amp = filt.amp_by_time(signal, Fs, f_range, filter_kwargs={'N_seconds': .5})
    assert len(signal) == len(amp)

    # Test results are the same if add NaNs to the side
    signal_nan = np.pad(signal, 10,
                        mode='constant',
                        constant_values=(np.nan,))
    amp_nan = filt.amp_by_time(signal_nan, Fs, f_range, filter_kwargs={'N_seconds': .5})
    np.testing.assert_allclose(amp_nan[10:-10], amp)

    # Test NaN is in same places as filtered signal
    signal_filt = filt.bandpass_filter(signal, Fs, (6, 14), N_seconds=.5)
    assert np.all(np.logical_not(
                  np.logical_xor(np.isnan(amp), np.isnan(signal_filt))))

    # Test works fine if input signal already has NaN
    signal_low = filt.lowpass_filter(signal, Fs, 30, N_seconds=.3)
    amp = filt.amp_by_time(signal_low, Fs, f_range,
                           filter_kwargs={'N_seconds': .5})
    assert len(signal) == len(amp)

    # Test option to not remove edge artifacts
    amp = filt.amp_by_time(signal, Fs, f_range,
                           filter_kwargs={'N_seconds': .5},
                           remove_edge_artifacts=False)
    assert np.all(np.logical_not(np.isnan(amp)))
Exemplo n.º 3
0
def test_lowpass():
    """Test lowpass filter functionality"""

    # Load signal
    signal = np.load(data_path + 'sim_bursting.npy')
    Fs = 1000  # Sampling rate

    # Test output same length as input
    N_seconds = 0.5
    signal_filt = filt.lowpass_filter(signal, Fs, 30,
                                      N_seconds=N_seconds)
    assert len(signal) == len(signal_filt)

    # Test edge artifacts removed appropriately
    N_samples_filter = int(np.ceil(Fs * N_seconds))
    if N_samples_filter % 2 == 0:
        N_samples_filter = int(N_samples_filter + 1)
    N_samples_NaN = int(np.ceil(N_samples_filter / 2))
    assert np.all(np.isnan(signal_filt[:N_samples_NaN]))
    assert np.all(np.isnan(signal_filt[-N_samples_NaN:]))
    assert np.all(np.logical_not(np.isnan(
        signal_filt[N_samples_NaN:-N_samples_NaN])))

    # Test edge artifacts are not removed if desired
    signal_filt = filt.bandpass_filter(signal, Fs, (8, 12),
                                       N_seconds=N_seconds,
                                       remove_edge_artifacts=False)
    assert np.all(np.logical_not(np.isnan(signal_filt)))
Exemplo n.º 4
0
def test_lowpass():
    """Test lowpass filter."""

    # Load signal
    signal = np.load(DATA_PATH + 'sim_bursting.npy')
    Fs = 1000

    # Test output same length as input
    N_seconds = 0.5
    signal_filt, _ = filt.lowpass_filter(signal, Fs, 30, return_kernel=True)
    signal_filt = filt.lowpass_filter(signal,
                                      Fs,
                                      30,
                                      N_seconds=N_seconds,
                                      plot_frequency_response=True)
    assert len(signal) == len(signal_filt)

    # Test edge artifacts removed appropriately
    N_samples_filter = int(np.ceil(Fs * N_seconds))
    if N_samples_filter % 2 == 0:
        N_samples_filter = int(N_samples_filter + 1)
    N_samples_NaN = int(np.ceil(N_samples_filter / 2))
    assert np.all(np.isnan(signal_filt[:N_samples_NaN]))
    assert np.all(np.isnan(signal_filt[-N_samples_NaN:]))
    assert np.all(
        np.logical_not(np.isnan(signal_filt[N_samples_NaN:-N_samples_NaN])))

    # Test edge artifacts are not removed if desired
    signal_filt = filt.bandpass_filter(signal,
                                       Fs, (8, 12),
                                       N_seconds=N_seconds,
                                       remove_edge_artifacts=False)
    assert np.all(np.logical_not(np.isnan(signal_filt)))
Exemplo n.º 5
0
def test_bandpass():
    """Test bandpass filter functionality"""

    # Load signal
    signal = np.load(data_path + 'sim_bursting.npy')
    Fs = 1000  # Sampling rate

    # Test output same length as input
    N_seconds = 0.5
    signal_filt = filt.bandpass_filter(signal, Fs, (8, 12),
                                       N_seconds=N_seconds)
    assert len(signal) == len(signal_filt)

    # Test edge artifacts removed appropriately
    N_samples_filter = int(np.ceil(Fs * N_seconds))
    if N_samples_filter % 2 == 0:
        N_samples_filter = int(N_samples_filter + 1)
    N_samples_NaN = int(np.ceil(N_samples_filter / 2))
    assert np.all(np.isnan(signal_filt[:N_samples_NaN]))
    assert np.all(np.isnan(signal_filt[-N_samples_NaN:]))
    assert np.all(np.logical_not(np.isnan(
        signal_filt[N_samples_NaN:-N_samples_NaN])))

    # Test edge artifacts are not removed if desired
    signal_filt = filt.bandpass_filter(signal, Fs, (8, 12),
                                       N_seconds=N_seconds,
                                       remove_edge_artifacts=False)
    assert np.all(np.logical_not(np.isnan(signal_filt)))

    # Test returns kernel and signal
    out = filt.bandpass_filter(signal, Fs, (8, 12), N_seconds=N_seconds,
                               return_kernel=True)
    assert len(out) == 2

    # Test same result if N_cycle and N_seconds used
    filt1 = filt.bandpass_filter(signal, Fs, (8, 12), N_seconds=1,
                                 remove_edge_artifacts=False)
    filt2 = filt.bandpass_filter(signal, Fs, (8, 12), N_cycles=8,
                                 remove_edge_artifacts=False)
    np.testing.assert_allclose(filt1, filt2)
Exemplo n.º 6
0
def test_phase():
    """Test phase time series."""

    # Load signal
    signal = np.load(DATA_PATH + 'sim_bursting.npy')
    Fs = 1000
    f_range = (6, 14)

    # Test output same length as input
    pha = filt.phase_by_time(signal, Fs, f_range, hilbert_increase_N=True)
    pha = filt.phase_by_time(signal,
                             Fs,
                             f_range,
                             filter_kwargs={'N_seconds': .5})
    assert len(signal) == len(pha)

    # Test results are the same if add NaNs to the side
    signal_nan = np.pad(signal,
                        10,
                        mode='constant',
                        constant_values=(np.nan, ))
    pha_nan = filt.phase_by_time(signal_nan,
                                 Fs,
                                 f_range,
                                 filter_kwargs={'N_seconds': .5})
    np.testing.assert_allclose(pha_nan[10:-10], pha)

    # Test NaN is in same places as filtered signal
    signal_filt = filt.bandpass_filter(signal, Fs, (6, 14), N_seconds=.5)
    assert np.all(
        np.logical_not(np.logical_xor(np.isnan(pha), np.isnan(signal_filt))))

    # Test works fine if input signal already has NaN
    signal_low = filt.lowpass_filter(signal, Fs, 30, N_seconds=.3)
    pha = filt.phase_by_time(signal_low,
                             Fs,
                             f_range,
                             filter_kwargs={'N_seconds': .5})
    assert len(signal) == len(pha)

    # Test option to not remove edge artifacts
    pha = filt.phase_by_time(signal,
                             Fs,
                             f_range,
                             filter_kwargs={'N_seconds': .5},
                             remove_edge_artifacts=False)
    assert np.all(np.logical_not(np.isnan(pha)))
tlim = (2, 5)
tidx = np.logical_and(t>=tlim[0], t<tlim[1])

plt.figure(figsize=(12, 2))
plt.plot(t[tidx], signal[tidx], '.5')
plt.plot(t[tidx], signal_low[tidx], 'k')
plt.xlim(tlim)



#%% 
from bycycle.filt import bandpass_filter

# for attenuation problems

bandpass_filter(signal, Fs, (4, 10), N_seconds=.75, plot_frequency_response=True)
N_seconds = [0.1, 0.2, 0.5, 1, 2]
  

for jj in range(len(N_seconds)):
    
  # for every channel with pac
    for ii in range(10,15):
        
        # for every channel that has peaks
        if ~np.isnan(features_df['CF'][ii]):
        
            # define phase providing band
            CF = features_df['CF'][ii]
            BW = features_df['BW'][ii]
            
Exemplo n.º 8
0
def find_extrema(x,
                 Fs,
                 f_range,
                 boundary=None,
                 first_extrema='peak',
                 filter_kwargs=None):
    """
    Identify peaks and troughs in a time series.

    Parameters
    ----------
    x : 1d array
        voltage time series
    Fs : float
        sampling rate, Hz
    f_range : tuple of (float, float)
        frequency range (Hz) for narrowband signal of interest,
        used to find zerocrossings of the oscillation
    boundary : int
        number of samples from edge of recording to ignore
    first_extrema: {'peak', 'trough', None}
        if 'peak', then force the output to begin with a peak and end in a trough
        if 'trough', then force the output to begin with a trough and end in peak
        if None, force nothing
    filter_kwargs : dict
        keyword arguments to the filt.bandpass_filter(), such as 'N_cycles' or 'N_seconds'
        to control filter length

    Returns
    -------
    Ps : 1d array
        indices at which oscillatory peaks occur in the input signal x
    Ts : 1d array
        indices at which oscillatory troughs occur in the input signal x

    Notes
    -----
    This function assures that there are the same number of peaks and troughs
    if the first extrema is forced to be either peak or trough.
    """

    # Set default filtering parameters
    if filter_kwargs is None:
        filter_kwargs = {}

    # Default boundary value as 1 cycle length of low cutoff frequency
    if boundary is None:
        boundary = int(np.ceil(Fs / float(f_range[0])))

    # Narrowband filter signal
    x_filt = bandpass_filter(x,
                             Fs,
                             f_range,
                             remove_edge_artifacts=False,
                             **filter_kwargs)

    # Find rising and falling zerocrossings (narrowband)
    zeroriseN = _fzerorise(x_filt)
    zerofallN = _fzerofall(x_filt)

    # Compute number of peaks and troughs
    if zeroriseN[-1] > zerofallN[-1]:
        P = len(zeroriseN) - 1
        T = len(zerofallN)
    else:
        P = len(zeroriseN)
        T = len(zerofallN) - 1

    # Calculate peak samples
    Ps = np.zeros(P, dtype=int)
    for p in range(P):
        # Calculate the sample range between the most recent zero rise
        # and the next zero fall
        mrzerorise = zeroriseN[p]
        nfzerofall = zerofallN[zerofallN > mrzerorise][0]
        # Identify time fo peak
        Ps[p] = np.argmax(x[mrzerorise:nfzerofall]) + mrzerorise

    # Calculate trough samples
    Ts = np.zeros(T, dtype=int)
    for tr in range(T):
        # Calculate the sample range between the most recent zero fall
        # and the next zero rise
        mrzerofall = zerofallN[tr]
        nfzerorise = zeroriseN[zeroriseN > mrzerofall][0]
        # Identify time of trough
        Ts[tr] = np.argmin(x[mrzerofall:nfzerorise]) + mrzerofall

    # Remove peaks and troughs within the boundary limit
    Ps = Ps[np.logical_and(Ps > boundary, Ps < len(x) - boundary)]
    Ts = Ts[np.logical_and(Ts > boundary, Ts < len(x) - boundary)]

    # Force the first extrema to be as desired
    # Assure equal # of peaks and troughs
    if first_extrema == 'peak':
        if Ps[0] > Ts[0]:
            Ts = Ts[1:]
        if Ps[-1] > Ts[-1]:
            Ps = Ps[:-1]
    elif first_extrema == 'trough':
        if Ts[0] > Ps[0]:
            Ps = Ps[1:]
        if Ts[-1] > Ps[-1]:
            Ts = Ts[:-1]
    elif first_extrema is None:
        pass
    else:
        raise ValueError('Parameter "first_extrema" is invalid')

    return Ps, Ts
Exemplo n.º 9
0
# -----------------------------
#
# In order to characterize the oscillation, it is useful to know the precise times of peaks and
# troughs. For one, this will allow us to compute the periods and rise-decay symmetries of the
# individual cycles. To do this, the signal is first narrow-bandpass filtered in order to estimate
# "zero-crossings." Then, in between these zerocrossings, the absolute maxima and minima are found
# and labeled as the peaks and troughs, respectively.

from bycycle.filt import bandpass_filter
from bycycle.cyclepoints import _fzerorise, _fzerofall, find_extrema

# Narrowband filter signal
N_seconds_theta = .75
signal_narrow = bandpass_filter(signal,
                                Fs,
                                f_theta,
                                remove_edge_artifacts=False,
                                N_seconds=N_seconds_theta)

# Find rising and falling zerocrossings (narrowband)
zeroriseN = _fzerorise(signal_narrow)
zerofallN = _fzerofall(signal_narrow)

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

# Find peaks and troughs (this function also does the above)
Ps, Ts = find_extrema(signal_low,
                      Fs,
                      f_theta,
                      filter_kwargs={'N_seconds': N_seconds_theta})
# plt.show()

plt.plot(t[tidx], signal_low[tidx], 'k')
plt.xlim(tlim)
plt.title('lowpass 100 Hz signal - trial 1')
plt.show()

#localizing peaks and troughs
from bycycle.filt import bandpass_filter
from bycycle.cyclepoints import _fzerorise, _fzerofall, find_extrema

# Narrowband filter signal
N_seconds_theta = 0.02
signal_narrow = bandpass_filter(signal,
                                Fs,
                                f_theta,
                                remove_edge_artifacts=False,
                                N_seconds=N_seconds_theta)

# plt.plot(t[tidx], signal[tidx], '.5')
# plt.plot(t[tidx], signal_narrow[tidx], 'k')
# plt.xlim(tlim)
# plt.title('bandpass compared to raw')
# plt.show()

#Find rising and falling zerocrossings (narrowband)
zeroriseN = _fzerorise(signal_narrow)
zerofallN = _fzerofall(signal_narrow)

Ps, Ts = find_extrema(signal_low,
                      Fs,
# ---------------------------------------------------------------

import numpy as np
import scipy as sp
from scipy import signal as spsignal
import matplotlib.pyplot as plt
from bycycle.filt import amp_by_time, phase_by_time, bandpass_filter
from bycycle.sim import sim_noisy_bursty_oscillator

signal = np.load('data/sim_bursting_more_noise.npy')
Fs = 1000  # Sampling rate
f_alpha = (8, 12)
N_seconds_filter = .5

# Compute amplitude and phase
signal_filt = bandpass_filter(signal, Fs, f_alpha, N_seconds=N_seconds_filter)
theta_amp = amp_by_time(signal,
                        Fs,
                        f_alpha,
                        filter_kwargs={'N_seconds': N_seconds_filter})
theta_phase = phase_by_time(signal,
                            Fs,
                            f_alpha,
                            filter_kwargs={'N_seconds': N_seconds_filter})

# Plots signal
t = np.arange(0, len(signal) / Fs, 1 / Fs)
tlim = (2, 6)
tidx = np.logical_and(t >= tlim[0], t < tlim[1])

plt.figure(figsize=(12, 6))