def foof2mat_customfreq(): import sys import hdf5storage import sklearn from scipy import io import scipy import numpy as np from fooof import FOOOF import neurodsp import matplotlib.pyplot as plt import pacpy import h5py import matplotlib from matplotlib import lines import math from neurodsp import spectral # FOOOF imports: get FOOOF & FOOOFGroup objects from fooof import FOOOFGroup slpa = [] ra = [] dat = hdf5storage.loadmat(str(sys.argv[1])) frq_ax = np.linspace(0, 1000, 10001) #dat["fx"][0] pwr_spectra = dat['avgpwr'] #dat["powall"] for fl in range(30, 100, 2): for ul in range(50, 300, 2): if fl < ul: # pwr_spectra=x['x'] # Initialize a FOOOFGroup object - it accepts all the same settings as FOOOF fg = FOOOFGroup(max_n_peaks=6, peak_threshold=4) frange = (fl, ul) # Fit a group of power spectra with the .fit() method# Fit a # The key difference (compared to FOOOF) is that it takes a 2D array of spectra # This matrix should have the shape of [n_spectra, n_freqs] fg.fit(frq_ax, pwr_spectra, frange) slp = fg.get_all_data('background_params', 'slope') r = fg.get_all_data('r_squared') slpa = np.concatenate((slpa, slp)) ra = np.concatenate((ra, r)) scipy.io.savemat('slpa.mat', {'slpa': slpa}) scipy.io.savemat('ra.mat', {'ra': ra}) return
def fooof_channel_rejection(eeg, psds, freqs, f_low, f_high, participant, session_name): from scipy.stats import bayes_mvs n_bads = 0 fooof_group = FOOOFGroup(max_n_peaks=6, min_peak_amplitude=0.1, peak_width_limits=[1, 12], background_mode='knee') fooof_group.fit(freqs, psds, freq_range=[f_low, f_high / 2], n_jobs=-1) fooof_group_fig = fooof_group.plot(save_fig=True, file_name='FOOOF_group_' + participant + '_' + session_name, file_path=data_dir + '/results/') bg_slope = fooof_group.get_all_data('background_params', col='slope') mean_cntr, var_cntr, std_cntr = bayes_mvs(bg_slope, alpha=0.9) lower_slope = mean_cntr[1][0] - std_cntr[1][1] upper_slope = mean_cntr[1][1] + std_cntr[1][1] print('upper and lower slope range (mean, std)', lower_slope, upper_slope, np.mean(bg_slope), np.std(bg_slope)) for channel_idx, slope in enumerate(bg_slope): if slope < lower_slope or slope > upper_slope: eeg.info['bads'].append(eeg.ch_names[channel_idx]) n_bads += 1 eeg.interpolate_bads(reset_bads=True) return eeg, n_bads
aperiodic_params=param_sampler([[20, 2], [35, 1.5]]), gauss_params=param_sampler([[], [10, 0.5, 2]])) ################################################################################################### # Fit FOOOF models across the group of synthesized power spectra fg = FOOOFGroup(peak_width_limits=[1, 8], min_peak_height=0.05, max_n_peaks=6, verbose=False) fg.fit(freqs, spectra) ################################################################################################### # Get all alpha oscillations from a FOOOFGroup object alphas = get_band_peak_group(fg.get_all_data('peak_params'), alpha_band, len(fg)) ################################################################################################### # Check out some of the alpha data print(alphas[0:5, :]) ################################################################################################### # # Note that the design of :func:`get_band_peak_group` is such that it will retain # information regarding which oscillation came from with model fit. # # To do so, it's output is organized such that each row corresponds to a specific # model fit, such that the matrix returned is size [n_fits, 3]. #
def main(): # Get project database objects, and list of available subjects db = SLFDB() subjs = db.check_subjs() done = db.get_fooof_subjs() for cur_subj in subjs: # Skip specified subjects if cur_subj in SKIP_SUBJS: print('\n\n\nSKIPPING SUBJECT: ', str(cur_subj), '\n\n\n') continue # Skip subject if PSD already calculated if cur_subj in done: print('\n\n\nSUBJECT ALREADY RUN: ', str(cur_subj), '\n\n\n') continue # Print status print('\n\n\nRUNNING SUBJECT: ', str(cur_subj), '\n\n\n') # Get subject data files try: dat_f, ev_f, _ = db.get_subj_files(cur_subj) if dat_f is None: print('\n\n\nSKIPPING DUE TO FILE ISSUE: ', str(cur_subj), '\n\n\n') continue except: print('\tFAILED TO GET SUBJ FILES') continue # Get the resting data file - file 001 temp = [ef.split('_')[1] for ef in ev_f] temp = [fn[-3:] for fn in temp] f_ind = None for i, tt in enumerate(temp): if tt == '001': f_ind = i if f_ind is None: print('\tFAILED TO FIND 001 BLOCK') continue # Get file file path for data file & associated event file dat_f_name = db.gen_dat_path(cur_subj, dat_f[f_ind]) eve_f_name = db.gen_dat_path(cur_subj, ev_f[f_ind]) # Set the sampling rate s_freq = 500 # Load data file dat = np.loadtxt(dat_f_name, delimiter=',') # Read in list of channel names that are kept in reduced 111 montage with open('../data/chans111.csv', 'r') as csv_file: reader = csv.reader(csv_file) ch_labels = list(reader)[0] # Read montage, reduced to 111 channel selection montage = mne.channels.read_montage('GSN-HydroCel-129', ch_names=ch_labels) # Create the info structure needed by MNE info = mne.create_info(ch_labels, s_freq, 'eeg', montage) # Create the MNE Raw data object raw = mne.io.RawArray(dat, info) # Create a stim channel stim_info = mne.create_info(['stim'], s_freq, 'stim') stim_raw = mne.io.RawArray(np.zeros(shape=[1, len(raw._times)]), stim_info) # Add stim channel to data object raw.add_channels([stim_raw], force_update_info=True) # Load events from file # Initialize headers and variable to store event info headers = ['type', 'value', 'latency', 'duration', 'urevent'] evs = np.empty(shape=[0, 3]) # Load events from csv file with open(eve_f_name, 'r') as csv_file: reader = csv.reader(csv_file) for row in reader: # Skip the empty rows if row == []: continue # Skip the header row, since there is one for every event... if row[0] == 'type': continue # Collect actual event data rows evs = np.vstack((evs, np.array([int(row[2]), 0, int(row[0])]))) # Add events to data object raw.add_events(evs, stim_channel='stim') # Check events dat_evs = mne.find_events(raw) # Find flat channels and set them as bad flat_chans = np.mean(raw._data[:111, :], axis=1) == 0 raw.info['bads'] = list(np.array(raw.ch_names[:111])[flat_chans]) print('Bad channels: ', raw.info['bads']) # Interpolate bad channels raw.interpolate_bads() # Set average reference raw.set_eeg_reference() raw.apply_proj() # Get good eeg channel indices eeg_chans = mne.pick_types(raw.info, meg=False, eeg=True) # Epoch resting eeg data events eo_epochs = mne.Epochs(raw, events=dat_evs, event_id={'EO': 20}, tmin=2, tmax=18, baseline=None, picks=eeg_chans, preload=True) ec_epochs = mne.Epochs(raw, events=dat_evs, event_id={'EC': 30}, tmin=5, tmax=35, baseline=None, picks=eeg_chans, preload=True) # Calculate PSDs - EO Data eo_psds, eo_freqs = mne.time_frequency.psd_welch(eo_epochs, fmin=2., fmax=40., n_fft=1000, n_overlap=250, verbose=False) # Average PSDs for each channel across each rest block eo_avg_psds = np.mean(eo_psds, axis=0) # Calculate PSDs - EC Data ec_psds, ec_freqs = mne.time_frequency.psd_welch(ec_epochs, fmin=2., fmax=40., n_fft=1000, n_overlap=250, verbose=False) # Average PSDs for each channel across each rest block ec_avg_psds = np.mean(ec_psds, axis=0) # Save out PSDs np.savez(os.path.join(db.psd_path, str(cur_subj) + '_ec_avg_psds.npz'), ec_freqs, ec_avg_psds, np.array(ec_epochs.ch_names)) np.savez(os.path.join(db.psd_path, str(cur_subj) + '_eo_avg_psds.npz'), eo_freqs, eo_avg_psds, np.array(eo_epochs.ch_names)) np.savez(os.path.join(db.psd_path, str(cur_subj) + '_ec_psds.npz'), ec_freqs, ec_psds, np.array(ec_epochs.ch_names)) np.savez(os.path.join(db.psd_path, str(cur_subj) + '_eo_psds.npz'), eo_freqs, eo_psds, np.array(eo_epochs.ch_names)) # Print status print('\n\n\nPSD DATA SAVED FOR SUBJ: ', str(cur_subj), '\n\n\n') print('\n\n\nFOOOFING DATA FOR SUBJ: ', str(cur_subj), '\n\n\n') # Fit FOOOF to PSDs averaged across rest epochs fg = FOOOFGroup(peak_width_limits=[1, 8], max_n_peaks=6) fg.fit(eo_freqs, eo_avg_psds, F_RANGE) sls_eo_avg = fg.get_all_data('background_params', 'slope') fg.fit(ec_freqs, ec_avg_psds, F_RANGE) sls_ec_avg = fg.get_all_data('background_params', 'slope') # Fit FOOOF to PSDs from each epoch eo_fgs = [] for ep_psds in eo_psds: fg.fit(eo_freqs, ep_psds, F_RANGE) eo_fgs.append(fg.copy()) sls_eo = [ fg.get_all_data('background_params', 'slope') for fg in eo_fgs ] ec_fgs = [] for ep_psds in ec_psds: fg.fit(ec_freqs, ep_psds, F_RANGE) ec_fgs.append(fg.copy()) sls_ec = [ fg.get_all_data('background_params', 'slope') for fg in ec_fgs ] # Collect data together subj_dat = { 'ID': cur_subj, 'sls_eo_avg': sls_eo_avg, 'sls_ec_avg': sls_ec_avg, 'sls_eo': sls_eo, 'sls_ec': sls_ec } # Save out slope data f_name = str(cur_subj) + '_fooof.p' save_pickle(subj_dat, f_name, db.fooof_path) # Print status print('\n\n\nFOOOF DATA SAVED AND FINISHED WITH SUBJ: ', str(cur_subj), '\n\n\n')
print(fg.group_results[0:2]) ################################################################################################### # get_all_data # ------------ # # To collect data across all model fits, and to select specific data results from this data # you can use the :func:`get_all_data` method. This method lets you extract specific results # by specifying a field, as a string, and (optionally) a specific column of that data, also # as a string (or, optionally, as an integer index). # ################################################################################################### # Extract aperiodic data aps = fg.get_all_data('aperiodic_params') exps = fg.get_all_data('aperiodic_params', 'exponent') # Extract peak data peaks = fg.get_all_data('peak_params') cfs = fg.get_all_data('peak_params', 'CF') # Extract metadata about the model fit errors = fg.get_all_data('error') r2s = fg.get_all_data('r_squared') ################################################################################################### # The full list of data you can specify is available in the documentation of :func:`get_all_data` print(fg.get_all_data.__doc__)
############################################################################### # Use :func:`get_band_peak` to extract oscillations from a single FOOOF model # Extract any beta band oscillations from the FOOOF model get_band_peak(fm.peak_params_, beta_band) ############################################################################### # # The :func:`get_band_peak` function will extract peaks within a specified band from the results of a FOOOF fit. # # You can optionally specify whether to return all oscillations within that band, or a singular result, which returns the highest power peak (if there are multiple). ############################################################################### # Get all alpha oscillations from a FOOOFGroup object alphas = get_band_peak_group(fg.get_all_data('peak_params'), alpha_band, len(fg)) ############################################################################### # Check out some of the alpha data alphas[0:5, :] ############################################################################### # **get_band_peak_group** # # Note that the design of :func:`get_band_peak_group` is such that it will retain information regarding which oscillation came from with model fit. # # To do so, it's output is organized such that each row corresponds to a specific model fit, such that the matrix returned is size [n_fits, 3]. # # For this to work, at most 1 peak is extracted for each model fit within the specified band.
10, [3, 50], ap_opts, gauss_opts) ################################################################################################### # Initialize a FOOOFGroup fg = FOOOFGroup(peak_width_limits=[1, 6]) ################################################################################################### # Fit FOOOF and report on the group fg.report(freqs, power_spectra) ################################################################################################### # Find the index of the worst FOOOF fit from the group worst_fit_ind = np.argmax(fg.get_all_data('error')) # Extract this FOOOF fit from the group, into a FOOOF object fm = fg.get_fooof(worst_fit_ind, regenerate=True) ################################################################################################### # # Check out the model fit of the extracted FOOOF model fm.print_results() fm.plot() ################################################################################################### # # You can also loop through all the results in a test group, extracting all fits # that meet some criterion that makes them worth checking. #
############################################################################### # As it runs, FOOOFGroup collects each fit results in 'group_results' # 'group_results' is a list of FOOOFResult objects fg.group_results[0:2] ############################################################################### # **get_all_data** # # To collect data across all model fits, and to select specific data results from this data you can use the :func:`get_all_data` method. This method lets you extract specific results by specifying a field, as a string, and (optionally) a specific column of that data, also as a string (or, optionally, as an integer index). ############################################################################### # Extract aperiodic data bgps = fg.get_all_data('background_params') sls = fg.get_all_data('background_params', 'slope') # Extract peak data peaks = fg.get_all_data('peak_params') cfs = fg.get_all_data('peak_params', 'CF') # Extract metadata about the model fit errors = fg.get_all_data('error') r2s = fg.get_all_data('r_squared') ############################################################################### # The full list of data you can specify is available in the documentation of :func:`get_all_data` print(fg.get_all_data.__doc__)
################################################################################################### # Fit the 3D matrix of power spectra fgs = fit_fooof_group_3d(fg, fs, spectra) ################################################################################################### # This returns a list of FOOOFGRoup objects print(fgs) ################################################################################################### # Compare the aperiodic exponent results across conditions for ind, fg in enumerate(fgs): print("Aperiodic exponent for condition {} is {:1.4f}".format( ind, np.mean(fg.get_all_data('aperiodic_params', 'exponent')))) ################################################################################################### # combine_fooofs # -------------- # # Depending what the organization of the data is, you might also want to collapse # FOOOF models dimensions that have been fit. # # # To do so, you can use the :func:`combine_fooofs` function, which takes # a list of FOOOF or FOOOFGroup objects, and combines them together into # a single FOOOFGroup object (assuming the settings and data definitions # are consistent to do so). ###################################################################################################