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)))
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)))
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)))
def plot_trial(monkey, d, el, trial, f_beta, filtered=True): ## import packages import numpy as np import matplotlib.pyplot as plt from bycycle.filt import lowpass_filter import pandas as pd from bycycle.filt import bandpass_filter pd.options.display.max_columns = 50 Fs = 781 length_data = 1564 data_load = get_data(monkey, d) ## make trials signals = data_load[el, (trial - 1) * length_data:(trial * length_data)] signals = lowpass_filter(signals, Fs, 40, N_seconds=.1, remove_edge_artifacts=False) signals = signals[391:1172] #if filtered == True: # signals = bandpass_filter(signals, Fs, f_beta, N_cycles=2, remove_edge_artifacts=False) # plot signal T = len(signals) / Fs t = np.arange(0, T, 1 / Fs) fig, ax = plt.subplots(figsize=(16, 3)) ax.plot(t, signals, 'k') #ax.xlim((0, T)) return ax
def test_detect_bursts_df_amp(): """Test amplitude-threshold burst detection.""" # Load signal signal = np.load(DATA_PATH + 'sim_bursting.npy') Fs = 1000 f_range = (6, 14) signal = filt.lowpass_filter(signal, Fs, 30, N_seconds=.3, remove_edge_artifacts=False) # Compute cycle-by-cycle df without burst detection column df = features.compute_features(signal, 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 = burst.detect_bursts_df_amp(df, signal, 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
def spindle_detect_bycycle(): import sys import numpy as np import scipy as sp from scipy import io import matplotlib.pyplot as plt from bycycle.filt import lowpass_filter from bycycle.features import compute_features import pandas import hdf5storage signal_all = hdf5storage.loadmat(str(sys.argv[1])) signal_all = signal_all["lfp"]["trial"][0][0][0] refch_all = range(0, len(signal_all)) Fs = 1000 f_lowpass = 40 N_seconds = .25 for refch in refch_all: signal = signal_all[refch, :] signal_low = lowpass_filter(signal, Fs, f_lowpass, N_seconds=N_seconds, remove_edge_artifacts=False) from bycycle.burst import plot_burst_detect_params burst_kwargs = { 'amplitude_fraction_threshold': float(sys.argv[2]), 'amplitude_consistency_threshold': float(sys.argv[3]), 'period_consistency_threshold': float(sys.argv[4]), 'monotonicity_threshold': float(sys.argv[5]), 'N_cycles_min': 4 } #burst_kwargs = {'amplitude_fraction_threshold': .5, # 'amplitude_consistency_threshold': .3, # 'period_consistency_threshold': .5, # 'monotonicity_threshold': .7, # 'N_cycles_min': 4} df = compute_features(signal_low, Fs, (8.5, 19), burst_detection_kwargs=burst_kwargs, hilbert_increase_N=True) df_csv = pandas.DataFrame.to_csv(df) df_dir = "spindle_detect\spindle_peaks" + str(refch) + ".csv" csv = open(df_dir, "w") csv.write(df_csv) return
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)))
def test_detect_bursts_cycles(): """Test amplitude and period consistency burst detection""" # Load signal signal = np.load(data_path + 'sim_bursting.npy') Fs = 1000 # Sampling rate f_range = (6, 14) # Frequency range signal = filt.lowpass_filter(signal, Fs, 30, N_seconds=.3, remove_edge_artifacts=False) # Compute cycle-by-cycle df without burst detection column df = features.compute_features(signal, 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_cycles = burst.detect_bursts_cycles(df, signal) # Make sure that burst detection is only boolean assert df_burst_cycles.dtypes['is_burst'] == 'bool' assert df_burst_cycles['is_burst'].mean() > 0 assert df_burst_cycles['is_burst'].mean() < 1 assert np.min([ sum(1 for _ in group) for key, group in itertools.groupby(df_burst_cycles['is_burst']) if key ]) >= 3
# define phase providing band CF = features_df['CF'][ii] BW = features_df['BW'][ii] # only for now, delete with new FOOOF if BW < 5: phase_providing_band= [(CF - (BW/2))-1, (CF + (BW/2))+1] else: phase_providing_band= [(CF - (BW/2)), (CF + (BW/2))] subj = features_df['subj'][ii] ch = features_df['ch'][ii] ep = features_df['ep'][ii] data = datastruct[subj][ch][ep] signal = lowpass_filter(data, fs, f_lowpass, N_seconds=N_seconds, remove_edge_artifacts=False) bycycle_df = compute_features(signal, fs, phase_providing_band, burst_detection_kwargs=burst_kwargs) # # plot_burst_detect_params(signal, fs, bycycle_df, # burst_kwargs, tlims=(0, 5), figsize=(16, 3), plot_only_result=True) # # plot_burst_detect_params(signal, fs, bycycle_df, # burst_kwargs, tlims=(0, 5), figsize=(16, 3)) # find biggest length with no violations # We have to ensure that the index is sorted bycycle_df.sort_index(inplace=True) # Resetting the index to create a column bycycle_df.reset_index(inplace=True)
############################################################################### # # Load simulated experiment of 10 patients and 10 controls # -------------------------------------------------------- ############################################################################### # Load experimental data signals = np.load('data/sim_experiment.npy') Fs = 1000 # Sampling rate # Apply lowpass filter to each signal for i in range(len(signals)): signals[i] = lowpass_filter(signals[i], Fs, 30, N_seconds=.2, remove_edge_artifacts=False) ############################################################################### # Plot an example signal N = len(signals) T = len(signals[0]) / Fs t = np.arange(0, T, 1 / Fs) plt.figure(figsize=(16, 3)) plt.plot(t, signals[0], 'k') plt.xlim((0, T)) plt.show()
# get subj & ch subj = subj_idx[ii] ch = ch_idx[ii] ep = ep_idx[ii] # get phase providing band lower_phase = psd_peaks[subj][ch][ep][0] - (psd_peaks[subj][ch][ep][2] / 2) upper_phase = psd_peaks[subj][ch][ep][0] + (psd_peaks[subj][ch][ep][2] / 2) fs = 1000 f_range = [lower_phase, upper_phase] f_lowpass = 55 N_seconds = len(datastruct[subj][ch]) / fs / num_epochs - 2 signal = lowpass_filter(datastruct[subj][ch][(ep*fs*epoch_len):((ep*fs*epoch_len)+fs*epoch_len)], fs, f_lowpass, N_seconds=N_seconds, remove_edge_artifacts=False) df = compute_features(signal, fs, f_range, burst_detection_kwargs=burst_kwargs) is_burst = df['is_burst'].tolist() time_rdsym = df['time_rdsym'].to_numpy() time_ptsym = df['time_ptsym'].to_numpy() period_ch = df['period'].to_numpy() volt_amp_ch = df['volt_amp'].to_numpy() bursts.append(is_burst) rdsym.append(time_rdsym) ptsym.append(time_ptsym) period.append(period_ch) volt_amp.append(volt_amp_ch)
nperseg=fs * 2) # Initialize FOOOF model fm = FOOOF(peak_width_limits=bw_lims, background_mode='fixed', max_n_peaks=max_n_peaks, min_peak_amplitude=min_peak_amplitude) # fit model fm.fit(freq_mean, psd_mean, freq_range) # run ByCycle # low pass filter lp_signal = lowpass_filter(signal, fs, f_lowpass, N_seconds=n_seconds_kernal, remove_edge_artifacts=False) # bycycle dataframe bycycle_df = compute_features(lp_signal, fs, [osc_freq_rand - 2, osc_freq_rand + 2], burst_detection_kwargs=burst_kwargs) # calculate PAC #calculating phase of theta phase_data = butter_bandpass_filter(signal, osc_freq_rand - 1, osc_freq_rand + 1, fs) phase_data_hilbert = hilbert(phase_data) phase_data_angle = np.angle(phase_data_hilbert)
pd.options.display.max_columns = 30 #################################################################################################### # Load data signal = np.load('data/ca1.npy') / 1000 signal = signal[:125000] Fs = 1250 f_theta = (4, 10) f_lowpass = 30 N_seconds = .1 # Lowpass filter signal_low = lowpass_filter(signal, Fs, f_lowpass, N_seconds=N_seconds, remove_edge_artifacts=False) # Plot signal t = np.arange(0, len(signal) / Fs, 1 / Fs) 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) plt.tight_layout() plt.show()
BW = features_df['BW'][ii] # only for now, delete with new FOOOF if BW < 5: phase_providing_band = [(CF - (BW / 2)) - 1, (CF + (BW / 2)) + 1] else: phase_providing_band = [(CF - (BW / 2)), (CF + (BW / 2))] subj = features_df['subj'][ii] ch = features_df['ch'][ii] ep = features_df['ep'][ii] data = datastruct[subj][ch][ep] signal = lowpass_filter(data, fs, f_lowpass, N_seconds=N_seconds, remove_edge_artifacts=False) bycycle_df = compute_features(signal, fs, phase_providing_band, burst_detection_kwargs=burst_kwargs) # # plot_burst_detect_params(signal, fs, bycycle_df, # burst_kwargs, tlims=(0, 5), figsize=(16, 3), plot_only_result=True) # # plot_burst_detect_params(signal, fs, bycycle_df, # burst_kwargs, tlims=(0, 5), figsize=(16, 3)) #
def identify_bursts(monkey, days, f_beta, f_lowpass, Fs): ''' :param monkey: Satan or Risette :param days: range of days, starts at 1 :param f_beta: frequency range of interest, e.g. (4,40) :param f_lowpass: integer for lowpass filter, e.g. 40 :param Fs: samplting frequency :param n_bins: number of bins for time analysis, e.g. 8 :return: ''' # ------------------------------------------------------------------------ # 1. import packages # ------------------------------------------------------------------------ import numpy as np from bycycle.filt import lowpass_filter import pandas as pd pd.options.display.max_columns = 50 from bycycle.filt import bandpass_filter from bycycle.cyclepoints import _fzerorise, _fzerofall, find_extrema from bycycle.features import compute_features # ------------------------------------------------------------------------ # Define parameters # ------------------------------------------------------------------------ length_trial = 1564 # ------------------------------------------------------------------------ # 2. load and select data # ------------------------------------------------------------------------ df_all = [] for d in days: print('Identifying bursts for day', d) data = get_data(monkey, d) n_trials = data.shape[1] // length_trial n_el = data.shape[0] # ------------------------------------------------------------------------ # 3. Prepare data # ------------------------------------------------------------------------ for el in range(n_el): # initialize condition array per electrode signals_raw = [] # will contain all trials as array # separate into trials for trial in range(n_trials): signals_raw.append(data[el, trial * length_trial:((trial + 1) * length_trial)]) # lowpass filter # aim: remove slow transients or high frequency activity that may interfer with peak and trough identification signals_filtered = [] for signals_raw_trial in signals_raw: signals_filtered.append( lowpass_filter(signals_raw_trial, Fs, f_lowpass, N_seconds=.2, remove_edge_artifacts=False)) # ------------------------------------------------------------------------ # 4. cycle feature computation # ------------------------------------------------------------------------ burst_kwargs = { 'amplitude_fraction_threshold': .3, 'amplitude_consistency_threshold': .4, 'period_consistency_threshold': .5, 'monotonicity_threshold': .8, 'N_cycles_min': 3 } dfs = [] for trial, signal_filtered_narrow_trial in enumerate( signals_filtered): df = compute_features(signal_filtered_narrow_trial, Fs, f_beta, burst_detection_kwargs=burst_kwargs) # only take bursts that are within 1000 ms delay df = df.loc[(df['sample_last_trough'] >= 392) & (df['sample_next_trough'] <= 1172)] df = df.reset_index() df['trial'] = trial + 1 # Search df['electrode'] = el df['day'] = d dfs.append(df) df_cycles = pd.concat(dfs) # make panda df df_all.append(df_cycles) df_all = pd.concat(df_all) df_all.to_pickle(monkey + '_dfBurstRaw_' + str(f_beta)) return df_all
if (psd_peaks[subj][ch][0] < 15) & (psd_peaks[subj][ch][1] > .2) & (psd_peaks[subj][ch][1] < 1.5): # get phase providing band lower_phase = psd_peaks[subj][ch][0] - (psd_peaks[subj][ch][2] / 2) upper_phase = psd_peaks[subj][ch][0] + (psd_peaks[subj][ch][2] / 2) fs = 1000 f_range = [lower_phase, upper_phase] f_lowpass = 55 N_seconds = len(datastruct[subj][ch]) / fs - 2 signal = lowpass_filter(datastruct[subj][ch], fs, f_lowpass, N_seconds=N_seconds, remove_edge_artifacts=False) df = compute_features(signal, fs, f_range, burst_detection_kwargs=burst_kwargs) is_burst = df['is_burst'].tolist() time_rdsym = df['time_rdsym'].to_numpy() time_ptsym = df['time_ptsym'].to_numpy() bursts.append(is_burst) rdsym.append(time_rdsym) ptsym.append(time_ptsym)