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
Esempio n. 2
0
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
Esempio n. 3
0
    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].
#
Esempio n. 4
0
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')
Esempio n. 5
0
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.
#
Esempio n. 8
0
###############################################################################

# 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__)
Esempio n. 9
0
###################################################################################################

# 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).

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