def filterEEG(eeg_data, fs=250, f_range=(1, 50)):
    sig_filt = filt.filter_signal(eeg_data, fs, 'bandpass', f_range, filter_type='iir', butterworth_order=2)
    test_sig_filt = filt.filter_signal(sig_filt, fs, 'bandstop', (58, 62), n_seconds=1)
    num_nans = sum(np.isnan(test_sig_filt))
    sig_filt = np.concatenate(([0]*(num_nans // 2), sig_filt, [0]*(num_nans // 2)))
    sig_filt = filt.filter_signal(sig_filt, fs, 'bandstop', (58, 62), n_seconds=1)
    sig_filt = sig_filt[~np.isnan(sig_filt)]
    return sig_filt
Exemplo n.º 2
0
def get_bandpass_filter_signal(data, fs, f_range, passtype='bandpass'):
    sig_filt = filt.filter_signal(data,
                                  fs,
                                  passtype,
                                  f_range,
                                  remove_edges=False)
    return sig_filt
def bandpass_bandstop_filter(data,fs=250, lowcut=1, highcut=50, order = 2):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    sos = butter(order, [low, high], analog = False, btype = 'band', output = 'sos')
    filted_data = sosfiltfilt(sos, data)
    filted_data = filt.filter_signal(filted_data, fs, 'bandstop', (58, 62), n_seconds=1)
    filted_data = filted_data[~np.isnan(filted_data)]
    return filted_data
Exemplo n.º 4
0
def phase_by_time(sig,
                  fs,
                  f_range=None,
                  hilbert_increase_n=False,
                  remove_edges=True,
                  **filter_kwargs):
    """Compute the instantaneous phase of a time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float or None, optional default: None
        Filter range, in Hz, as (low, high). If None, no filtering is applied.
    hilbert_increase_n : bool, optional, default: False
        If True, zero pad the signal's length to the next power of 2 for the Hilbert transform.
        This is because ``scipy.signal.hilbert`` can be very slow for some lengths of x.
    remove_edges : bool, optional, default: True
        If True, replace samples that are within half of the filter's length to the edge with nan.
        This removes edge artifacts from the filtered signal. Only used if `f_range` is defined.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    pha : 1d array
        Instantaneous phase time series.

    Examples
    --------
    Compute the instantaneous phase, for the alpha range:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation': {'freq': 10}})
    >>> pha = phase_by_time(sig, fs=500, f_range=(8, 12))
    """

    if f_range:
        sig, filter_kernel = filter_signal(sig,
                                           fs,
                                           infer_passtype(f_range),
                                           f_range=f_range,
                                           remove_edges=False,
                                           return_filter=True,
                                           **filter_kwargs)

    pha = np.angle(robust_hilbert(sig, increase_n=hilbert_increase_n))

    if f_range and remove_edges:
        pha = remove_filter_edges(pha, len(filter_kernel))

    return pha
Exemplo n.º 5
0
def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs):
    """Generate a power law time series with specified exponent by spectrally rotating white noise.

    Parameters
    ----------
    n_seconds : float
        Simulation time, in seconds.
    fs : float
        Sampling rate of simulated signal, in Hz.
    exponent : float
        Desired power-law exponent, of the form P(f)=f^exponent.
    f_range : list of [float, float] or None, optional
        Frequency range to filter simulated data, as [f_lo, f_hi], in Hz.
    **filter_kwargs : kwargs, optional
        Keyword arguments to pass to `filter_signal`.

    Returns
    -------
    sig: 1d array
        Time-series with the desired power-law exponent.
    """

    n_samples = int(n_seconds * fs)
    sig = np.random.randn(n_samples)

    # Compute the FFT
    fft_output = np.fft.fft(sig)
    freqs = np.fft.fftfreq(len(sig), 1. / fs)

    # Rotate spectrum and invert, zscore to normalize.
    #   Note: the delta exponent to be applied is divided by two, as
    #     the FFT output is in units of amplitude not power
    fft_output_rot = rotate_powerlaw(freqs, fft_output, -exponent/2)
    sig = zscore(np.real(np.fft.ifft(fft_output_rot)))

    if f_range is not None:
        filter_signal(sig, fs, infer_passtype(f_range), f_range, **filter_kwargs)

    return sig
Exemplo n.º 6
0
def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs):
    """Simulate a power law time series, with a specified exponent.

    Parameters
    ----------
    n_seconds : float
        Simulation time, in seconds.
    fs : float
        Sampling rate of simulated signal, in Hz.
    exponent : float, optional, default: -2
        Desired power-law exponent, of the form P(f)=f^exponent.
    f_range : list of [float, float] or None, optional
        Frequency range to filter simulated data, as [f_lo, f_hi], in Hz.
    **filter_kwargs : kwargs, optional
        Keyword arguments to pass to `filter_signal`.

    Returns
    -------
    sig: 1d array
        Time-series with the desired power law exponent.
    """

    # Get the number of samples to simulate for the signal
    #   If filter is to be filtered, with FIR, add extra to compensate for edges
    if f_range and filter_kwargs.get('filter_type', None) != 'iir':

        pass_type = infer_passtype(f_range)
        filt_len = compute_filter_length(fs, pass_type,
                                         *check_filter_definition(pass_type, f_range),
                                         n_seconds=filter_kwargs.get('n_seconds', None),
                                         n_cycles=filter_kwargs.get('n_cycles', 3))

        n_samples = int(n_seconds * fs) + filt_len + 1

    else:
        n_samples = int(n_seconds * fs)

    sig = _create_powerlaw(n_samples, fs, exponent)

    if f_range is not None:
        sig = filter_signal(sig, fs, infer_passtype(f_range), f_range,
                            remove_edges=True, **filter_kwargs)
        # Drop the edges, that were compensated for, if not using IIR (using FIR)
        if not filter_kwargs.get('filter_type', None) == 'iir':
            sig, _ = remove_nans(sig)

    return sig
Exemplo n.º 7
0
def amp_by_time(sig, fs, f_range=None, remove_edges=True, **filter_kwargs):
    """Compute the instantaneous amplitude of a time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float or None, optional default: None
        Filter range, in Hz, as (low, high). If None, no filtering is applied.
    remove_edges : bool, optional, default: True
        If True, replace samples that are within half of the filter's length to the edge with nan.
        This removes edge artifacts from the filtered signal. Only used if `f_range` is defined.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    amp : 1d array
        Instantaneous amplitude time series.

    Examples
    --------
    Compute the instantaneous amplitude, for the alpha range:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> amp = amp_by_time(sig, fs=500, f_range=(8, 12))
    """

    if f_range:
        sig, filter_kernel = filter_signal(sig,
                                           fs,
                                           infer_passtype(f_range),
                                           f_range=f_range,
                                           remove_edges=False,
                                           return_filter=True,
                                           **filter_kwargs)

    amp = np.abs(robust_hilbert(sig))

    if f_range and remove_edges:
        amp = remove_filter_edges(amp, len(filter_kernel))

    return amp
Exemplo n.º 8
0
def amp_by_time(sig,
                fs,
                f_range=None,
                hilbert_increase_n=False,
                remove_edges=True,
                **filter_kwargs):
    """Compute the instantaneous amplitude of a time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float or None, optional default: None
        Filter range, in Hz, as (low, high). If None, no filtering is applied.
    hilbert_increase_n : bool, optional, default: False
        If True, zero pad the signal to length the next power of 2 when doing the Hilbert transform.
        This is because :func:`scipy.signal.hilbert` can be very slow for some lengths of sig.
    remove_edges : bool, optional, default: True
        If True, replace samples that are within half of the filters length to the edge with np.nan.
        This removes edge artifacts from the filtered signal. Only used if `f_range` is defined.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    amp : 1d array
        Instantaneous amplitude time series.
    """

    if f_range:
        sig, filter_kernel = filter_signal(sig,
                                           fs,
                                           infer_passtype(f_range),
                                           f_range=f_range,
                                           remove_edges=False,
                                           return_filter=True,
                                           **filter_kwargs)

    amp = np.abs(robust_hilbert(sig, increase_n=hilbert_increase_n))

    if f_range and remove_edges:
        amp = remove_filter_edges(amp, len(filter_kernel))

    return amp
Exemplo n.º 9
0
def amp_by_time(sig,
                fs,
                f_range,
                hilbert_increase_n=False,
                remove_edges=True,
                **filter_kwargs):
    """Calculate the amplitude time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float
        The frequency filtering range, in Hz, as (low, high).
    hilbert_increase_n : bool, optional, default: False
        If True, zeropad the signal to length the next power of 2 when doing the hilbert transform.
        This is because scipy.signal.hilbert can be very slow for some lengths of sig.
    remove_edges : bool, optional, default: True
        If True, replace the samples that are within half a kernel's length to
        the signal edge with np.nan.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    amp : 1d array
        Time series of amplitude.
    """

    sig_filt, kernel = filter_signal(sig,
                                     fs,
                                     infer_passtype(f_range),
                                     f_range=f_range,
                                     remove_edges=False,
                                     return_filter=True,
                                     **filter_kwargs)

    amp = np.abs(robust_hilbert(sig_filt, increase_n=hilbert_increase_n))

    if remove_edges:
        amp = remove_filter_edges(amp, len(kernel))

    return amp
Exemplo n.º 10
0
def test_detect_bursts_df_amp():
    """Test amplitude-threshold burst detection."""

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

    fs = 1000
    f_range = (6, 14)

    sig_filt = filter_signal(sig,
                             fs,
                             'lowpass',
                             30,
                             n_seconds=.3,
                             remove_edges=False)

    # Compute cycle-by-cycle df without burst detection column
    df = compute_features(sig_filt,
                          fs,
                          f_range,
                          burst_detection_method='amp',
                          burst_detection_kwargs={
                              'amp_threshes': (1, 2),
                              'filter_kwargs': {
                                  'n_seconds': .5
                              }
                          })
    df.drop('is_burst', axis=1, inplace=True)

    # Apply consistency burst detection
    df_burst_amp = detect_bursts_df_amp(df,
                                        sig_filt,
                                        fs,
                                        f_range,
                                        amp_threshes=(.5, 1),
                                        n_cycles_min=4,
                                        filter_kwargs={'n_seconds': .5})

    # Make sure that burst detection is only boolean
    assert df_burst_amp.dtypes['is_burst'] == 'bool'
    assert df_burst_amp['is_burst'].mean() > 0
    assert df_burst_amp['is_burst'].mean() < 1
    assert np.min([sum(1 for _ in group) for key, group \
        in itertools.groupby(df_burst_amp['is_burst']) if key]) >= 4
Exemplo n.º 11
0
def find_extrema(sig,
                 fs,
                 f_range,
                 boundary=0,
                 first_extrema='peak',
                 filter_kwargs=None,
                 pass_type='bandpass',
                 pad=True):
    """Identify peaks and troughs in a time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of (float, float)
        Frequency range, in Hz, to narrowband filter the signal, used to find zero-crossings.
    boundary : int, optional, default: 0
        Number of samples from edge of the signal 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, optional, default: None
        Keyword arguments to :func:`~neurodsp.filt.filter.filter_signal`,
        such as 'n_cycles' or 'n_seconds' to control filter length.
    pass_type : str, optional, default: 'bandpass'
        Which kind of filter pass_type is consistent with the frequency definition provided.
    pad : bool, optional, default: True
        Whether to pad ``sig`` with zeros to prevent missed cyclepoints at the edges.

    Returns
    -------
    peaks : 1d array
        Indices at which oscillatory peaks occur in the input ``sig``.
    troughs : 1d array
        Indices at which oscillatory troughs occur in the input ``sig``.

    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.

    Examples
    --------
    Find the locations of peaks and burst in a signal:

    >>> from neurodsp.sim import sim_bursty_oscillation
    >>> fs = 500
    >>> sig = sim_bursty_oscillation(10, fs, freq=10)
    >>> peaks, troughs = find_extrema(sig, fs, f_range=(8, 12))
    """

    # Ensure arguments are within valid range
    check_param_range(fs, 'fs', (0, np.inf))

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

    # Get the original signal and filter lengths
    sig_len = len(sig)
    filt_len = 0

    # Pad beginning of signal with zeros to prevent missing cyclepoints
    if pad:

        filt_len = compute_filter_length(
            fs,
            pass_type,
            f_range[0],
            f_range[1],
            n_seconds=filter_kwargs.get('n_seconds', None),
            n_cycles=filter_kwargs.get('n_cycles', 3))

        # Pad the signal
        sig = np.pad(sig, int(np.ceil(filt_len / 2)), mode='constant')

    # Narrowband filter signal
    sig_filt = filter_signal(sig,
                             fs,
                             pass_type,
                             f_range,
                             remove_edges=False,
                             **filter_kwargs)

    # Find rising and decaying zero-crossings (narrowband)
    rise_xs = find_flank_zerox(sig_filt, 'rise')
    decay_xs = find_flank_zerox(sig_filt, 'decay')

    # Compute number of peaks and troughs
    if rise_xs[-1] > decay_xs[-1]:
        n_peaks = len(rise_xs) - 1
        n_troughs = len(decay_xs)
    else:
        n_peaks = len(rise_xs)
        n_troughs = len(decay_xs) - 1

    # Calculate peak samples
    peaks = np.zeros(n_peaks, dtype=int)
    for p_idx in range(n_peaks):

        # Calculate the sample range between the most recent zero rise and the next zero decay
        last_rise = rise_xs[p_idx]
        next_decay = decay_xs[decay_xs > last_rise][0]
        # Identify time of peak
        peaks[p_idx] = np.argmax(sig[last_rise:next_decay]) + last_rise

    # Calculate trough samples
    troughs = np.zeros(n_troughs, dtype=int)
    for t_idx in range(n_troughs):

        # Calculate the sample range between the most recent zero decay and the next zero rise
        last_decay = decay_xs[t_idx]
        next_rise = rise_xs[rise_xs > last_decay][0]
        # Identify time of trough
        troughs[t_idx] = np.argmin(sig[last_decay:next_rise]) + last_decay

    # Remove padding
    peaks = peaks - int(np.ceil(filt_len / 2))
    troughs = troughs - int(np.ceil(filt_len / 2))

    # Remove peaks and trough outside the boundary limit
    peaks = peaks[np.logical_and(peaks > boundary, peaks < sig_len - boundary)]
    troughs = troughs[np.logical_and(troughs > boundary,
                                     troughs < sig_len - boundary)]

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

    return peaks, troughs
fs = 1000
# sampling frequency in Hz
times = rawdata['tx_14']  # time vector
times = (times).T

print(f"DATA: (n_trials, n_times)={data.shape}; SAMPLING FREQUENCY={fs}Hz; "
      f"TIME VECTOR: n_times={len(times)}")

# Define a frequency range to filter the data
sig = np.mean(data, axis=0)
f_range = (2, 12)

# Bandpass filter the data, across the band of interest
sig_filt = filter_signal(sig,
                         fs,
                         'bandpass',
                         f_range,
                         filter_type='iir',
                         butterworth_order=4)

# Plot filtered signal
# fig = plt.figure(figsize=(14, 6))
plot_time_series(times, [sig, sig_filt], ['Raw', 'Filtered'])
# plt.show()

fig = plt.figure(figsize=(14, 6))
# adding the mean PSD over trials
# plt.subplot(1, 2, 1)
plt.plot(times, sig, color='black')
plt.plot(times, sig_filt, color='red', linewidth=5.0)
plt.ylim([-50, 50])
# plt.xlim([-1000, 0])
####################################################################################################
#
# Load simulated experiment of 10 patients and 10 controls
# --------------------------------------------------------

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

# Load experimental data
sigs = np.load('data/sim_experiment.npy')
fs = 1000  # Sampling rate

# Apply lowpass filter to each signal
for idx in range(len(sigs)):
    sigs[idx] = filter_signal(sigs[idx],
                              fs,
                              'lowpass',
                              30,
                              n_seconds=.2,
                              remove_edges=False)

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

# Plot an example signal
n_signals = len(sigs)
n_seconds = len(sigs[0]) / fs
times = np.arange(0, n_seconds, 1 / fs)

plot_time_series(times, sigs[0], lw=2)

####################################################################################################
#
# Compute cycle-by-cycle features
Exemplo n.º 14
0
def find_extrema(sig,
                 fs,
                 f_range,
                 boundary=None,
                 first_extrema='peak',
                 filter_kwargs=None):
    """Identify peaks and troughs in a time series.

    Parameters
    ----------
    sig : 1d array
        Voltage time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of (float, float)
        Frequency range, in Hz, for narrowband signal of interest,
        used to find zero-crossings of the oscillation.
    boundary : int, optional
        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, optional
        Keyword arguments to :func:`~neurodsp.filt.filter.filter_signal`, such as 'n_cycles' or
        'n_seconds' to control filter length.

    Returns
    -------
    ps : 1d array
        Indices at which oscillatory peaks occur in the input ``sig``.
    ts : 1d array
        Indices at which oscillatory troughs occur in the input ``sig``.

    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
    sig_filt = filter_signal(sig,
                             fs,
                             'bandpass',
                             f_range,
                             remove_edges=False,
                             **filter_kwargs)

    # Find rising and falling zero-crossings (narrowband)
    zerorise_n = _fzerorise(sig_filt)
    zerofall_n = _fzerofall(sig_filt)

    # Compute number of peaks and troughs
    if zerorise_n[-1] > zerofall_n[-1]:
        pl = len(zerorise_n) - 1
        tl = len(zerofall_n)
    else:
        pl = len(zerorise_n)
        tl = len(zerofall_n) - 1

    # Calculate peak samples
    ps = np.zeros(pl, dtype=int)
    for p_idx in range(pl):

        # Calculate the sample range between the most recent zero rise and the next zero fall
        mrzerorise = zerorise_n[p_idx]
        nfzerofall = zerofall_n[zerofall_n > mrzerorise][0]
        # Identify time of peak
        ps[p_idx] = np.argmax(sig[mrzerorise:nfzerofall]) + mrzerorise

    # Calculate trough samples
    ts = np.zeros(tl, dtype=int)
    for t_idx in range(tl):

        # Calculate the sample range between the most recent zero fall and the next zero rise
        mrzerofall = zerofall_n[t_idx]
        nfzerorise = zerorise_n[zerorise_n > mrzerofall][0]
        # Identify time of trough
        ts[t_idx] = np.argmin(sig[mrzerofall:nfzerorise]) + mrzerofall

    # Remove peaks and troughs within the boundary limit
    ps = ps[np.logical_and(ps > boundary, ps < len(sig) - boundary)]
    ts = ts[np.logical_and(ts > boundary, ts < len(sig) - 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.º 15
0
#

###################################################################################################
# Using filter_signal
# ~~~~~~~~~~~~~~~~~~~
#
# In the above, we did a step-by-step procedure of designing, evaluating, and applying our filter.
#
# Note that all of these elements can also be done directly through the
# :func:`~.filter_signal` function.
#

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

sig_filt, sos = filter_signal(sig, fs, pass_type, f_range,
                              filter_type='iir', butterworth_order=butterworth_order,
                              plot_properties=True, print_transitions=True,
                              return_filter=True)

###################################################################################################
# Example Application: Line Noise Removal
# ---------------------------------------
#
# A common application of IIR filters is for line noise removal.
#
# In this example, a 3rd order Butterworth filter is applied to remove 60Hz noise.
#

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

# Generate a signal, with a low frequency oscillation and 60 Hz line noise
components = {'sim_oscillation' : [{'freq' : 6}, {'freq' : 60}]}
Exemplo n.º 16
0
# Generate a signal for this example, with an oscillation and 60 Hz line noise
components = {'sim_oscillation' : [{'freq' : 6}, {'freq' : 60}]}
variances = [1, 0.2]
sig = sim_combined(n_seconds, fs, components, variances)

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

# Define filter settings
f_range = (58, 62)
passtype = 'bandstop'

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

# Apply a short filter, one that won't achieve our desired attenuation
sig_filt_short = filter_signal(sig, fs, passtype, f_range,
                               n_seconds=0.25, plot_properties=True)

###################################################################################################
#
# Notice that when we apply the filter above, with a short filter length, we get a
# warning about the filter attenuation. The filter we have defined does not get to a
# sufficient attenuation level.
#

###################################################################################################v

# This user warning disappears if we elongate the filter
sig_filt_long = filter_signal(sig, fs, passtype, f_range,
                              n_seconds=1, plot_properties=True)

###################################################################################################
Exemplo n.º 17
0

# Simulation settings
n_seconds = 10
fs = 1000
components = {'sim_bursty_oscillation': {'freq': 10, 'enter_burst': .1, 'leave_burst': .1,
                                         'cycle': 'asine', 'rdsym': 0.3},
              'sim_powerlaw': {'f_range': (2, None)}}
sig = sim_combined(n_seconds, fs, components=components, component_variances=(2, 1))

# Filter settings
f_alpha = (8, 12)
n_seconds_filter = .5

# Compute amplitude and phase
sig_filt = filter_signal(sig, fs, 'bandpass', f_alpha, n_seconds=n_seconds_filter)
theta_amp = amp_by_time(sig, fs, f_alpha, n_seconds=n_seconds_filter)
theta_phase = phase_by_time(sig, fs, f_alpha, n_seconds=n_seconds_filter)

# Plot signal
times = create_times(n_seconds, fs)
xlim = (2, 6)
tidx = np.logical_and(times >= xlim[0], times < xlim[1])

fig, axes = plt.subplots(figsize=(15, 9), nrows=3)

# Plot the raw signal
plot_time_series(times[tidx], sig[tidx], ax=axes[0], ylabel='Voltage (mV)',
                 xlabel='', lw=2, labels='raw signal')

# Plot the filtered signal and oscillation amplitude
Exemplo n.º 18
0
#
# Extract signal within a specific frequency range (e.g. theta, 4-8 Hz).
#

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

# Generate an oscillation with noise
fs = 1000
times = create_times(4, 1000)
sig = np.random.randn(len(times)) + 5 * np.sin(times * 2 * np.pi * 6)

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

# Filter the data, across a frequency band of interest
f_range = (4, 8)
sig_filt = filt.filter_signal(sig, fs, 'bandpass', f_range)

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

# Plot filtered signal
plot_time_series(times, [sig, sig_filt], ['Raw', 'Filtered'])

###################################################################################################
#
# Notice that the edges of the filtered signal are clipped (no red).
#
# Edge artifact removal is done by default in :func:`filter_signal`, because
# the signal samples at the edges only experienced part of the filter.
#
# To bypass this feature, set `remove_edge_artifacts=False`, but at your own risk!
#
Exemplo n.º 19
0
def get_bandpass_filter_signal(data, fs, passtype, f_range):
    sig_filt = filt.filter_signal(data, fs, passtype, f_range)
    return sig_filt
def run_all(session):

    # get data session path from mat file
    path = get_session_path(session)

    # load position data from .mat file
    df = load_position(session)

    # load xml which has channel & fs info
    channels, fs, shank = loadXML(path)

    # get good channels
    good_ch = get_good_channels(shank)

    # load .lfp
    lfp, ts = loadLFP(glob.glob(path + '\*.lfp')[0],
                      n_channels=channels,
                      channel=good_ch,
                      frequency=fs,
                      precision='int16')

    # interp speed of the animal
    speed = np.interp(ts, df.ts, df.speed)
    speed[np.isnan(speed)] = 0

    # get filtered signal
    print('filtering signal')
    filtered_lfps = np.stack([
        filter_signal(lfp_, fs, 'bandpass', (80, 250), remove_edges=False)
        for lfp_ in lfp.T
    ])
    filtered_lfps = filtered_lfps.T

    # detect ripples

    print('detecting ripples')
    ripple_times = Karlsson_ripple_detector(ts, filtered_lfps, speed, fs)

    # find ripple duration
    ripple_times[
        'ripple_duration'] = ripple_times.end_time - ripple_times.start_time

    # check against emg (< 0.85)
    ripple_times = emg_filter(session, ripple_times, shank)

    # add ripple channel and peak amp
    print('getting ripple channel')
    ripple_times = get_ripple_channel(ripple_times,
                                      stats.zscore(filtered_lfps, axis=0), ts,
                                      fs)

    # get instant phase, amp, and freq
    print('get instant phase, amp, and freq')
    phase, amp, freq = get_phase_amp_freq(filtered_lfps, fs)

    # get ripple_map
    print('getting ripple maps')
    ripple_maps = get_ripple_maps(ripple_times, ts, lfp, filtered_lfps, phase,
                                  amp, freq, fs)

    # get ripple frequency
    print('getting ripple frequency')
    ripple_times['peak_freq'] = [
        map[len(map) // 2] for map in ripple_maps['freq_map']
    ]

    # filter out cliped signal
    ripple_times, ripple_maps = clip_filter(ripple_times, ripple_maps)

    # filter out very high amplitude ripples
    #ripple_times,ripple_maps = filter_high_amp(ripple_times,ripple_maps)

    # find ripples with a single large jump
    #ripple_times,ripple_maps = filter_single_peaks(ripple_times,ripple_maps)

    # save ripples for neuroscope inspection
    save_ripples(ripple_times, path)

    return ripple_times, lfp, filtered_lfps, ts, ripple_maps
Exemplo n.º 21
0
def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs):
    """Simulate a power law time series, with a specified exponent.

    Parameters
    ----------
    n_seconds : float
        Simulation time, in seconds.
    fs : float
        Sampling rate of simulated signal, in Hz.
    exponent : float, optional, default: -2
        Desired power-law exponent, of the form P(f)=f^exponent.
    f_range : list of [float, float] or None, optional
        Frequency range to filter simulated data, as [f_lo, f_hi], in Hz.
    **filter_kwargs : kwargs, optional
        Keyword arguments to pass to `filter_signal`.

    Returns
    -------
    sig : 1d array
        Time-series with the desired power law exponent.

    Notes
    -----
    - Powerlaw data with exponents is created by spectrally rotating white noise [1]_.

    References
    ----------
    .. [1] Timmer, J., & Konig, M. (1995). On Generating Power Law Noise.
           Astronomy and Astrophysics, 300, 707–710.

    Examples
    --------
    Simulate a power law signal, with an exponent of -2 (brown noise):

    >>> sig = sim_powerlaw(n_seconds=1, fs=500, exponent=-2.0)

    Simulate a power law signal, with a highpass filter applied at 2 Hz:

    >>> sig = sim_powerlaw(n_seconds=1, fs=500, exponent=-1.5, f_range=(2, None))
    """

    # Compute the number of samples for the simulated time series
    n_samples = compute_nsamples(n_seconds, fs)

    # Get the number of samples to simulate for the signal
    #   If signal is to be filtered, with FIR, add extra to compensate for edges
    if f_range and filter_kwargs.get('filter_type', None) != 'iir':

        pass_type = infer_passtype(f_range)
        filt_len = compute_filter_length(
            fs,
            pass_type,
            *check_filter_definition(pass_type, f_range),
            n_seconds=filter_kwargs.get('n_seconds', None),
            n_cycles=filter_kwargs.get('n_cycles', 3))

        n_samples += filt_len + 1

    # Simulate the powerlaw data
    sig = _create_powerlaw(n_samples, fs, exponent)

    if f_range is not None:
        sig = filter_signal(sig,
                            fs,
                            infer_passtype(f_range),
                            f_range,
                            remove_edges=True,
                            **filter_kwargs)
        # Drop the edges, that were compensated for, if not using FIR filter
        if not filter_kwargs.get('filter_type', None) == 'iir':
            sig, _ = remove_nans(sig)

    return sig
####################################################################################################

# Only keep 60 seconds of data
n_seconds = 60
ca1_raw = ca1_raw[:int(n_seconds * fs)]
ec3_raw = ec3_raw[:int(n_seconds * fs)]

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

# Apply a lowpass filter at 25Hz
fc = 25
filter_seconds = .5

ca1 = filter_signal(ca1_raw,
                    fs,
                    'lowpass',
                    fc,
                    n_seconds=filter_seconds,
                    remove_edges=False)
ec3 = filter_signal(ec3_raw,
                    fs,
                    'lowpass',
                    fc,
                    n_seconds=filter_seconds,
                    remove_edges=False)

####################################################################################################
# Compute cycle-by-cycle features
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

####################################################################################################
pd.options.display.max_columns = 10

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

# Load data
sig = np.load('data/ca1.npy') / 1000
sig = sig[:125000]
fs = 1250
f_theta = (4, 10)
f_lowpass = 30
n_seconds = .1

# Lowpass filter
sig_low = filter_signal(sig,
                        fs,
                        'lowpass',
                        f_lowpass,
                        n_seconds=n_seconds,
                        remove_edges=False)

# Plot signal
times = np.arange(0, len(sig) / fs, 1 / fs)
xlim = (2, 5)
tidx = np.logical_and(times >= xlim[0], times < xlim[1])

plot_time_series(times[tidx], [sig[tidx], sig_low[tidx]],
                 colors=['k', 'k'],
                 alpha=[.5, 1],
                 lw=2)

####################################################################################################
#
Exemplo n.º 24
0
        'freq': 10
    }, {
        'freq': 60
    }]
}
comp_vars = [0.5, 1, 1]

# Simulate a time series
sig = sim_combined(n_seconds, fs, components, comp_vars)

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

# Bandstop filter the signal to remove line noise frequencies
sig_filt = filter_signal(sig,
                         fs,
                         'bandstop', (57, 63),
                         n_seconds=2,
                         remove_edges=False)

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

# Compute a power spectrum of the simulated signal
freqs, powers_pre = trim_spectrum(*compute_spectrum(sig, fs), [3, 75])
freqs, powers_post = trim_spectrum(*compute_spectrum(sig_filt, fs), [3, 75])

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

# Plot the spectrum of the data, pre and post bandstop filtering
plot_spectra(freqs, [powers_pre, powers_post],
             log_powers=True,
             labels=['Pre-Filter', 'Post-Filter'])
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Now that we have a simulated signal, let's filter it into each of our frequency bands.
#
# To do so, we will loop across our band definitions, and plot the filtered version
# of the signal.
#

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

# Apply band-by-band filtering of our signal into each defined frequency band
_, axes = plt.subplots(len(bands), 1, figsize=(12, 15))
for ax, (label, f_range) in zip(axes, bands):

    # Filter the signal to the current band definition
    band_sig = filter_signal(sig, s_rate, 'bandpass', f_range)

    # Plot the time series of the current band, and adjust plot aesthetics
    plot_time_series(times, band_sig, title=label + ' ' + str(f_range), ax=ax,
                     xlim=(0, n_seconds), ylim=(-1, 1), xlabel='')

###################################################################################################
#
# As we can see, filtering a signal with aperiodic activity into arbitrary
# frequency ranges returns filtered signals that look like rhythmic activity.
#
# Also, because our simulated signal has some random variation, the filtered components
# also exhibit some fluctuations.
#
# Overall, we can see from filtering this signal that:
#
Exemplo n.º 26
0
    'sim_oscillation': {
        'freq': 6
    }
}
variances = [0.1, 1]

# Simulate our signal
sig = sim_combined(n_seconds, fs, components, variances)

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

# Define a frequency range to filter the data
f_range = (4, 8)

# Bandpass filter the data, across the band of interest
sig_filt = filter_signal(sig, fs, 'bandpass', f_range)

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

# Plot filtered signal
plot_time_series(times, [sig, sig_filt], ['Raw', 'Filtered'])

###################################################################################################
#
# Notice that the edges of the filtered signal are clipped (no red).
#
# Edge artifact removal is done by default in NeuroDSP filtering, because
# the signal samples at the edges only experienced part of the filter.
#
# To bypass this feature, set `remove_edges=False`, but at your own risk!
#
Exemplo n.º 27
0
# Using filter_signal
# ~~~~~~~~~~~~~~~~~~~
#
# In the above, we did a step-by-step procedure of designing, evaluating, and applying our filter.
#
# Note that all of these elements can also be done directly through the
# :func:`~.filter_signal` function.
#

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

# Filter our signal, using the main filter function, with extra options
sig_filt2, filter_kernel = filter_signal(sig,
                                         fs,
                                         pass_type,
                                         f_range,
                                         filter_type='fir',
                                         print_transitions=True,
                                         plot_properties=True,
                                         return_filter=True)

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

# Plot the signal and filtered version
plot_time_series(times, [sig, sig_filt2], ['Raw', 'Filtered'])

###################################################################################################
#
# You might notice in the above plot, the edges of the filtered version have been removed.
# This is done to remove edge artifacts. Data points at the edge of the signal don't get fully
# processed by the filter, and may contain some filtering artifacts.
#