Exemplo n.º 1
0
def fooofmodel():
    import sys
    import numpy as np
    from scipy.io import loadmat, savemat

    from fooof import FOOOFGroup
    import matplotlib.pyplot as plt

    data = loadmat('ModelPowSpctraForFOOOF.mat')

    # Unpack data from dictionary, and squeeze numpy arrays
    freqs = np.squeeze(data['fx']).astype('float')
    psds = np.squeeze(data['avgpwr']).astype('float')
    # ^Note: this also explicitly enforces type as float (type casts to float64, instead of float32)
    #  This is not strictly necessary for fitting, but is for saving out as json from FOOOF, if you want to do that

    # Transpose power spectra, to have the expected orientation for FOOOF
    #psds = psds.T
    fg = FOOOFGroup(peak_threshold=7,
                    peak_width_limits=[3, 14])  #, aperiodic_mode='knee'
    #fg.report(freqs, psds, [1, 290])
    #fg.fit(freqs,psds,[0.2,290])
    fg.fit(freqs, psds, [1, 290])
    fg.plot()
    fg.save_report('modelfits')

    slp = fg.get_params('aperiodic_params', 'exponent')
    off = fg.get_params('aperiodic_params', 'offset')
    r = fg.get_params('r_squared')

    savemat('slp.mat', {'slp': slp})
    savemat('off.mat', {'off': off})
    savemat('r.mat', {'r': r})
    return
Exemplo n.º 2
0
def create_report(subject, params):
    """ Collect parameters from the dialog and creates an FOOOFReport item
    """

    report_name = params['name']
    spectrum_name = params['spectrum_name']

    peak_width_low = params['peak_width_low']
    peak_width_high = params['peak_width_high']
    peak_threshold = params['peak_threshold']
    max_n_peaks = params['max_n_peaks']
    aperiodic_mode = params['aperiodic_mode']
    minfreq = params['minfreq']
    maxfreq = params['maxfreq']

    spectrum = subject.spectrum.get(spectrum_name)

    peak_width_limits = [peak_width_low, peak_width_high]
    peak_threshold = peak_threshold
    max_n_peaks = max_n_peaks
    aperiodic_mode = aperiodic_mode
    freq_range = [minfreq, maxfreq]

    # As meggie spectrum items can contain data for multiple conditions,
    # reports are also created for all those conditions, and dict is used.
    report_content = {}

    for key, data in spectrum.content.items():

        fg = FOOOFGroup(peak_width_limits=peak_width_limits,
                        peak_threshold=peak_threshold,
                        max_n_peaks=max_n_peaks,
                        aperiodic_mode=aperiodic_mode,
                        verbose=False)

        fg.fit(spectrum.freqs, data, freq_range)

        logging.getLogger('ui_logger').info('FOOOF results for ' +
                                            subject.name + ', ' +
                                            'condition: ' + key)
        # Log the textual report
        logging.getLogger('ui_logger').info(
            gen_results_fg_str(fg, concise=True))

        report_content[key] = fg

    params['conditions'] = list(spectrum.content.keys())
    params['ch_names'] = spectrum.ch_names

    fooof_directory = subject.fooof_report_directory

    # Create a container item that meggie understands,
    # and which holds the report data
    report = FOOOFReport(report_name, fooof_directory, params, report_content)

    # save report data to fs
    report.save_content()

    # and add the report item to subject
    subject.add(report, 'fooof_report')
Exemplo n.º 3
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
Exemplo n.º 4
0
def indiv_fooofcode():
    import sys
    import numpy as np
    from scipy.io import loadmat, savemat

    from fooof import FOOOFGroup
    import matplotlib.pyplot as plt

    patientcount = 16

    alloffset = []
    allr2 = []
    allexps = []
    allcfs = []

    for k in range(1,patientcount+1):
        matfile = 'indiv_' + str(k) + '.mat'
        data = loadmat(matfile)

        # Unpack data from dictionary, and squeeze numpy arrays
        freqs = np.squeeze(data['indiv_frq']).astype('float')
        psds = np.squeeze(data['indiv_pow']).astype('float')
        # ^Note: this also explicitly enforces type as float (type casts to float64, instead of float32)
        #  This is not strictly necessary for fitting, but is for saving out as json from FOOOF, if you want to do that
        fg = FOOOFGroup(peak_threshold=7,peak_width_limits=[3, 14])#, aperiodic_mode='knee'
        #fg.report(freqs, psds, [30, 300])
        #fg.fit(freqs,psds,[float(sys.argv[1]),float(sys.argv[2])])
        fg.fit(freqs,psds,[float(sys.argv[1]),float(sys.argv[2])])
        fg.plot()

        reportname = str(k) + '_indiv result'
        fg.save_report(reportname)

        #print(fg.group_results)

        r2 = fg.get_params('r_squared')
        allr2.append(r2)

        exps = fg.get_params('aperiodic_params', 'exponent')
        allexps.append(exps)

        centerfrq = fg.get_params('peak_params','CF')
        allcfs.append(centerfrq)

        offset = fg.get_params('aperiodic_params','offset')
        alloffset.append(offset)

        #knee = fg.get_params('aperiodic_params','knee')
        #savemat('knee_allpeeps.mat', {'knee' : knee})

    #NOW OUTSIDE OF BIG FORLOOP!
    #concat everythin.
    savemat('all_offset.mat',{'all_offset' : alloffset})
    savemat('all_r2.mat', {'all_r2' : allr2})
    savemat('all_exps.mat', {'all_exps' : allexps})
    savemat('all_cfs.mat',{'all_cfs' : allcfs}) #these are cell arrays! I didn't even mean for them to be but heck yea useful
Exemplo n.º 5
0
def get_tfg():
    """Get a FOOOFGroup object, with some fit power spectra, for testing."""

    n_spectra = 2
    xs, ys = gen_group_power_spectra(n_spectra, *default_group_params())

    tfg = FOOOFGroup()
    tfg.fit(xs, ys)

    return tfg
Exemplo n.º 6
0
def fooofy(components, spectra, freq_range):
    """
    A FOOOF Function, gets exponent parameters
    """
    fg = FOOOFGroup(max_n_peaks=0, aperiodic_mode='fixed', verbose = False) #initialize FOOOF object

    #print(spectra.shape, components.shape) #Use this line if things go weird

    fg.fit(components, spectra, freq_range) # THIS IS WHERE YOU SAY WHICH FREQ RANGE TO FIT
    m_array = fg.get_params('aperiodic_params', 'exponent')
    r2_array = fg.get_params('r_squared') #correlation between components (freqs or PCs) and spectra (powers or eigvals)
    #fg.r_squared_
    return m_array, r2_array
Exemplo n.º 7
0
def test_fg_fit_par():
    """Test FOOOFGroup fit, running in parallel."""

    n_spectra = 2
    xs, ys = gen_group_power_spectra(n_spectra, *default_group_params())

    tfg = FOOOFGroup()
    tfg.fit(xs, ys, n_jobs=2)
    out = tfg.get_results()

    assert out
    assert len(out) == n_spectra
    assert isinstance(out[0], FOOOFResult)
    assert np.all(out[1].background_params)
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
Exemplo n.º 9
0
def foof2mat_model():
    import sys
    from scipy.io import loadmat, savemat

    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

    dat = hdf5storage.loadmat(str(sys.argv[1]))
    frq_ax = np.linspace(0, 500, 5001)  #dat["fx"][0]
    pwr_spectra = dat['avgpwr']  #dat["powall"]

    #pwr_spectra=x['x']
    # Initialize a FOOOFGroup object - it accepts all the same settings as FOOOF
    fg = FOOOFGroup(peak_threshold=7,
                    peak_width_limits=[3, 14])  #, aperiodic_mode='knee'

    frange = (1, 290)

    # 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_params('aperiodic_params', 'exponent')
    off = fg.get_params('aperiodic_params', 'offset')
    r = fg.get_params('r_squared')

    savemat('slp.mat', {'slp': slp})
    savemat('off.mat', {'off': off})
    savemat('r.mat', {'r': r})
    return
Exemplo n.º 10
0
def fit_fooof(epochs):
    # Estimate the PSD in the pre-stimulus window
    spectrum, freqs = psd_welch(epochs, tmin=-.5, tmax=0,
                                fmin=2, fmax=30, n_fft=126,
                                average='median',
                                n_per_seg=100, n_overlap=50)
    spectrum = np.mean(spectrum, axis=0)

    # Run FOOF
    fm = FOOOFGroup(peak_width_limits=(4.0, 12.0),
                    aperiodic_mode='fixed',
                    peak_threshold=1)

    # Set the frequency range to fit the model
    freq_range = [2, 30]

    # Fit the FOOOF model
    fm.fit(freqs, spectrum, freq_range)
    return fm.copy()
Exemplo n.º 11
0
def fooofy(components, spectra, x_range, group=True):
    """
    fit FOOOF model on given spectrum and return params
        components: frequencies or PC dimensions
        spectra: PSDs or variance explained
        x_range: range for x axis of spectrum to fit
        group: whether to use FOOOFGroup or not
    """
    if group:
        fg = FOOOFGroup(max_n_peaks=0, aperiodic_mode='fixed', verbose=False) #initialize FOOOF object
    else:
        fg = FOOOF(max_n_peaks=0, aperiodic_mode='fixed', verbose=False) #initialize FOOOF object
    #print(spectra.shape, components.shape) #Use this line if things go weird

    fg.fit(components, spectra, x_range)
    exponents = fg.get_params('aperiodic_params', 'exponent')
    errors    = fg.get_params('error') # MAE
    offsets   = fg.get_params('aperiodic_params', 'offset')
    return exponents, errors, offsets
Exemplo n.º 12
0
def fooof_perps():
    import sys
    import numpy as np
    from scipy.io import loadmat, savemat

    from fooof import FOOOFGroup
    import matplotlib.pyplot as plt

    data = loadmat('perps_proper.mat')

    # Unpack data from dictionary, and squeeze numpy arrays
    freqs = np.squeeze(data['fx_regular']).astype('float')
    psds = np.squeeze(data['powa_regular']).astype('float')
    # ^Note: this also explicitly enforces type as float (type casts to float64, instead of float32)
    #  This is not strictly necessary for fitting, but is for saving out as json from FOOOF, if you want to do that

    # Transpose power spectra, to have the expected orientation for FOOOF
    #psds = psds.T
    fg = FOOOFGroup(peak_threshold=4,peak_width_limits=[3, 14])#, aperiodic_mode='knee'
    #fg.report(freqs, psds, [1, 290])
    #fg.fit(freqs,psds,[0.2,290])
    fg.fit(freqs,psds,[float(sys.argv[1]),float(sys.argv[2])])
    fg.plot()
    fg.save_report('perps')

    #print(fg.group_results)


    r2 = fg.get_params('r_squared')
    savemat('p_r2.mat', {'p_r2' : r2})

    exps = fg.get_params('aperiodic_params', 'exponent')
    centerfrq = fg.get_params('peak_params','CF')
    peakheight = fg.get_params('peak_params','PW')
    savemat('p_exps.mat', {'p_exps' : exps})
    savemat('p_cfs.mat', {'p_cfs' : centerfrq})
    savemat('p_peakheight.mat',{'p_peakheight' : peakheight})

    offset = fg.get_params('aperiodic_params','offset')
    savemat('p_offs.mat', {'p_offs' : offset})
Exemplo n.º 13
0
def compute_intsc(ts, numtps, srate, freq_range=(2, 50)):
    """
    Compute intrinsic neural timescale
    """

    # figure out tr in seconds
    tr = 1 / srate

    # grab electrode names
    colnames2use = ts.columns
    colnames2use = colnames2use.to_list()

    # normalize (divide all elements of the timeseries by the first value in the timeseries)
    ts = np.array(ts)
    for col_index, ts2use in enumerate(ts.T):
        ts[:, col_index] = np.divide(ts2use, ts2use[0])

    # compute spectrum via FFT
    f_axis = np.fft.fftfreq(numtps, tr)[:int(np.floor(numtps / 2))]
    psds = (np.abs(sp.fft(ts, axis=0))**2)[:len(f_axis)]

    # fit FOOOF & get knee parameter & convert to timescale
    fooof = FOOOFGroup(aperiodic_mode='knee', max_n_peaks=0, verbose=False)
    fooof.fit(freqs=f_axis, power_spectra=psds.T, freq_range=freq_range)
    fit_knee = fooof.get_params('aperiodic_params', 'knee')
    fit_exp = fooof.get_params('aperiodic_params', 'exponent')
    knee_freq, taus = convert_knee_val(fit_knee, fit_exp)

    # convert timescale into ms
    taus = taus * 1000

    # convert taus into a data frame
    taus_df = pd.DataFrame(taus.tolist(),
                           index=colnames2use,
                           columns=["intsc"])
    taus_df = taus_df.T

    return (taus_df)
Exemplo n.º 14
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')
Exemplo n.º 15
0
# Fit Power Spectrum Models
# ~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Now that we have our simulated data, we can fit our power spectrum models, using FOOOFGroup.
#

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

# Initialize a FOOOFGroup object for each group
fg1 = FOOOFGroup(verbose=False)
fg2 = FOOOFGroup(verbose=False)

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

# Parameterize neural power spectra
fg1.fit(freqs, powers1)
fg2.fit(freqs, powers2)

###################################################################################################
# Plotting Parameters & Components
# --------------------------------
#
# In the following, we will explore two visualization options:
#
# - plotting parameter values
# - plotting component reconstructions
#
# Each of these approaches can be done for either aperiodic or periodic parameters.
#
# All of the plots that we will use in this example can be used to visualize either
# one or multiple groups of data. As we will see, you can pass in a single group of
Exemplo n.º 16
0
# accessed in the same way as the FOOOF object.
#
# Internally, it runs the exact same fitting procedure, per spectrum, as the FOOOF object.
#

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

# Initialize a FOOOFGroup object - it accepts all the same settings as FOOOF
fg = FOOOFGroup(peak_width_limits=[1, 8], min_peak_height=0.05, max_n_peaks=6)

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

# Fit a group of power spectra with the .fit() method
#  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(freqs, spectra)

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

# Print out results
fg.print_results()

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

# Plot a summary of the results across the group
#  Note: given the simulations, we expect exponents at {1.5, 2.0. 2.5} and peaks around {10, 20}
fg.plot()

###################################################################################################
#
# Just as with the FOOOF object, you can call the convenience method `report` to run
Exemplo n.º 17
0
                print("Error: File not found!")
                continue

            print('Processing S%d B%d M%d ...' % (isubj, iblock, m))

            freqs = np.squeeze(dat['fxx'])
            aper = np.empty([2, dat['pxx'].shape[1]])
            only_gauss = np.zeros([dat['pxx'].shape[0], dat['pxx'].shape[1]])
            full_gauss = np.zeros([dat['pxx'].shape[0], dat['pxx'].shape[1]])

            fm = FOOOFGroup(peak_width_limits=[1, 8],
                            min_peak_height=0.05,
                            max_n_peaks=6)
            fm._maxfev = 30000
            freq_range = [3, 40]
            fm.fit(freqs, np.transpose(dat['pxx']), freq_range)
            tmp = fm.get_results()

            for isens in range(0, dat['pxx'].shape[1]):
                aper[:, isens] = tmp[isens].aperiodic_params

            F = fm.freqs

            for isens in range(0, dat['pxx'].shape[1]):
                for i in range(0, len(tmp[isens].gaussian_params)):
                    c = tmp[isens].gaussian_params[i][0]
                    w = tmp[isens].gaussian_params[i][2]
                    a = tmp[isens].gaussian_params[i][1]
                    only_gauss[:, isens] = only_gauss[:, isens] + a * np.exp(
                        (-(F - c)**2) / (2 * pow(w, 2)))
                b = tmp[isens].aperiodic_params[0]
Exemplo n.º 18
0
# Generate some synthetic power spectra and fit a FOOOFGroup to use
freqs, spectra, _ = gen_group_power_spectra(
    n_spectra=10,
    freq_range=[3, 40],
    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
Exemplo n.º 19
0
            third_half = np.mean(
                dat['pxx'][:, :,
                           sorted.size - int(np.floor(sorted.size / 3)) + 1:],
                axis=2)

            fm = FOOOFGroup(peak_width_limits=[1, 8],
                            min_peak_height=0.05,
                            max_n_peaks=6)
            fm._maxfev = 30000

            freq_range = [3, 40]

            freqs = np.squeeze(dat['fxx'])
            aperiodic = np.zeros([2, np.shape(dat['pxx'])[1], 2])

            fm.fit(freqs, np.transpose(first_half), freq_range)
            fm.save(
                '/home/tpfeffer/pp/proc/src/pp_hh_task_fooof_result_lo_s%d_b%d_v%d'
                % (isubj, iblock, v),
                save_results=True,
                save_settings=False,
                save_data=True)

            fm.fit(freqs, np.transpose(second_half), freq_range)
            fm.save(
                '/home/tpfeffer/pp/proc/src/pp_hh_task_fooof_result_me_s%d_b%d_v%d'
                % (isubj, iblock, v),
                save_results=True,
                save_settings=False,
                save_data=True)
Exemplo n.º 20
0
###################################################################################################

# Simulate some example power spectra to use for the example
freqs, powers = gen_group_power_spectra(25, [1, 50], [1, 1], [10, 0.25, 3],
                                        nlvs=0.1,
                                        freq_res=0.25)

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

# Initialize a FOOOFGroup object, with some desired settings
fg = FOOOFGroup(min_peak_height=0.1, max_n_peaks=6)

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

# Fit power spectra
fg.fit(freqs, powers)

###################################################################################################
#
# If there are failed fits, these are stored as null models.
#
# Let's check if there were any null models, from model failures, in the models
# that we have fit so far. To do so, the :class:`~fooof.FOOOFGroup` object has some
# attributes that provide information on any null model fits.
#
# These attributes are:
#
# - ``n_null_`` : the number of model results that are null
# - ``null_inds_`` : the indices of any null model results
#
Exemplo n.º 21
0
def main(argv):
    # defining paths
    basepath = '/Users/rdgao/Documents/data/MNI_rest/'
    datafile = basepath + 'WakefulnessMatlabFile.mat'
    result_basepath = '/Users/rdgao/Documents/code/research/field-echos/results/MNI_rest/'

    # load data
    data_dict = io.loadmat(datafile, squeeze_me=True)
    fs = data_dict['SamplingFrequency']
    data = data_dict['Data']

    if 'do_psds' in argv:
        print('Computing PSDs...')
        # 1 second window
        nperseg, noverlap = int(fs), int(fs / 2)
        f_axis, psd_mean, psd_med = compute_psds_whole(data, fs, nperseg,
                                                       noverlap)
        saveout_path = utils.makedir(result_basepath,
                                     'psd/1sec/',
                                     timestamp=False)
        np.savez(saveout_path + 'psds.npz',
                 psd_mean=psd_mean,
                 psd_med=psd_med,
                 f_axis=f_axis,
                 nperseg=nperseg,
                 noverlap=noverlap)

        # 5 second window
        nperseg, noverlap = int(fs * 5), int(fs * 4)
        f_axis, psd_mean, psd_med = compute_psds_whole(data, fs, nperseg,
                                                       noverlap)
        saveout_path = utils.makedir(result_basepath,
                                     '/psd/5sec/',
                                     timestamp=False)
        np.savez(saveout_path + 'psds.npz',
                 psd_mean=psd_mean,
                 psd_med=psd_med,
                 f_axis=f_axis,
                 nperseg=nperseg,
                 noverlap=noverlap)

    if 'do_fooof' in argv:
        print('FOOOFing...')
        fooof_settings = [['knee', 2, (1, 55)], ['fixed', 2, (1, 55)],
                          ['fixed', 1, (1, 10)], ['fixed', 1, (30, 55)]]

        for psd_win in ['1sec/', '5sec/']:
            psd_folder = result_basepath + '/psd/' + psd_win
            psd_data = np.load(psd_folder + 'psds.npz')
            for f_s in fooof_settings:
                # fit to mean and median psd
                for psd_mode in ['psd_mean', 'psd_med']:
                    fg = FOOOFGroup(aperiodic_mode=f_s[0], max_n_peaks=f_s[1])
                    fg.fit(psd_data['f_axis'],
                           psd_data[psd_mode].T,
                           freq_range=f_s[2])
                    fooof_savepath = utils.makedir(psd_folder,
                                                   '/fooof/' + psd_mode + '/',
                                                   timestamp=False)
                    fg.save('fg_%s_%ipks_%i-%iHz' %
                            (f_s[0], f_s[1], f_s[2][0], f_s[2][1]),
                            fooof_savepath,
                            save_results=True,
                            save_settings=True)

    print('Done.')
Exemplo n.º 22
0
# accessed in the same way as the :class:`~fooof.FOOOF` object.
#
# Internally, it runs the exact same fitting procedure, per spectrum, as the FOOOF object.
#

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

# Initialize a FOOOFGroup object, which accepts all the same settings as FOOOF
fg = FOOOFGroup(peak_width_limits=[1, 8], min_peak_height=0.05, max_n_peaks=6)

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

# Fit a group of power spectra with the .fit() method
#  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(freqs, spectra, [3, 30])

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

# Print out results
fg.print_results()

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

# Plot a summary of the results across the group
fg.plot()

###################################################################################################
#
# Just as with the FOOOF object, you can call the convenience method
# :meth:`fooof.FOOOFGroup.report` to run the fitting, and then print the results and plots.
                                       axis=-1,
                                       fs=200,
                                       window='hann',
                                       average='mean',
                                       nperseg=200,
                                       nfft=400,
                                       return_onesided=True)
    theta_params_clean = np.zeros(shape=[64, len(eps), 3]) - 1

    for elec_n in np.arange(n_elec):
        if np.logical_not(elec_n % 10):
            print('\telec : %s' % eps.info['ch_names'][elec_n])
        fg = FOOOFGroup(verbose=False,
                        max_n_peaks=4,
                        peak_width_limits=[.5, 2])
        fg.fit(freqs_welch, amp_welch[:, elec_n, :], [2, 20], n_jobs=-1)

        theta_params =\
         np.array([fg_res_n.peak_params[(fg_res_n.peak_params[:,0]>3.9)\
          & (fg_res_n.peak_params[:,0]<8)] for fg_res_n in fg.get_results()])
        for trial_n in np.arange(len(theta_params)):
            if len(theta_params[trial_n]) == 1:
                theta_params_clean[
                    elec_n, trial_n, :] = theta_params[trial_n].squeeze()
            elif len(theta_params[trial_n]) > 1:
                max_amp_ind = np.argmax(theta_params[trial_n][:, 1]).squeeze()
                theta_params_clean[elec_n, trial_n, :] = theta_params[trial_n][
                    max_amp_ind, :].squeeze()

    np.savez(obs_eegpath +\
     'obs_%i_fooof_params_theta.npz' % obs_i,
Exemplo n.º 24
0
    dat = scipy.io.loadmat(
        '/home/tpfeffer/pp/proc/src/pp_sens_gla_fooof_s%s_b1_v%d.mat' %
        (isubj + 1, v))

    fm = FOOOFGroup(peak_width_limits=[1, 8],
                    min_peak_height=0.05,
                    max_n_peaks=6)

    freq_range = [3, 40]

    freqs = np.squeeze(dat['fxx'])
    slp = np.zeros([np.shape(dat['pxx'])[1], np.shape(dat['pxx'])[2]])

    for iseg in range(0, np.shape(dat['pxx'])[2]):
        print('Processing segment %d' % iseg)
        power_spectrum = np.squeeze(dat['pxx'][:, :, iseg])
        spectrum = np.transpose(power_spectrum)
        fm.fit(freqs, spectrum, freq_range)
        tmp = fm.get_results()
        for isens in range(0, np.shape(dat['pxx'])[1]):
            slp[isens][iseg] = tmp[isens][0][1]

    r = np.zeros([np.shape(dat['pxx'])[1], 1])
    for iseg in range(0, np.shape(dat['pxx'])[1]):
        r[iseg] = np.corrcoef(slp[iseg, :], dat['pup'], rowvar=True)[0][1]

    scipy.io.savemat(
        '/home/tpfeffer/pp/proc/src/pp_sens_gla_fooof_exp_s%d.mat' %
        (isubj + 1), {'r': r})
Exemplo n.º 25
0
def main():

    #################################################
    ## SETUP

    ## Get list of subject files
    subj_files = listdir(DAT_PATH)
    subj_files = [file for file in subj_files if EXT.lower() in file.lower()]

    ## Set up FOOOF Objects
    # Initialize FOOOF settings & objects objects
    fooof_settings = FOOOFSettings(peak_width_limits=PEAK_WIDTH_LIMITS, max_n_peaks=MAX_N_PEAKS,
                                   min_peak_amplitude=MIN_PEAK_AMP, peak_threshold=PEAK_THRESHOLD,
                                   aperiodic_mode=APERIODIC_MODE)
    fm = FOOOF(*fooof_settings, verbose=False)
    fg = FOOOFGroup(*fooof_settings, verbose=False)

    # Save out a settings file
    fg.save('0-FOOOF_Settings', pjoin(RES_PATH, 'FOOOF'), save_settings=True)

    # Set up the dictionary to store all the FOOOF results
    fg_dict = dict()
    for load_label in LOAD_LABELS:
        fg_dict[load_label] = dict()
        for side_label in SIDE_LABELS:
            fg_dict[load_label][side_label] = dict()
            for seg_label in SEG_LABELS:
                fg_dict[load_label][side_label][seg_label] = []

    ## Initialize group level data stores
    n_subjs, n_conds, n_times = len(subj_files), 3, N_TIMES
    group_fooofed_alpha_freqs = np.zeros(shape=[n_subjs])
    dropped_components = np.ones(shape=[n_subjs, 50]) * 999
    dropped_trials = np.ones(shape=[n_subjs, 1500]) * 999
    canonical_group_avg_dat = np.zeros(shape=[n_subjs, n_conds, n_times])
    fooofed_group_avg_dat = np.zeros(shape=[n_subjs, n_conds, n_times])

    # Set channel types
    ch_types = {'LHor' : 'eog', 'RHor' : 'eog', 'IVer' : 'eog', 'SVer' : 'eog',
                'LMas' : 'misc', 'RMas' : 'misc', 'Nose' : 'misc', 'EXG8' : 'misc'}

    #################################################
    ## RUN ACROSS ALL SUBJECTS

    # Run analysis across each subject
    for s_ind, subj_file in enumerate(subj_files):

        # Get subject label and print status
        subj_label = subj_file.split('.')[0]
        print('\nCURRENTLY RUNNING SUBJECT: ', subj_label, '\n')

        #################################################
        ## LOAD / ORGANIZE / SET-UP DATA

        # Load subject of data, apply apply fixes for channels, etc
        eeg_dat = mne.io.read_raw_edf(pjoin(DAT_PATH, subj_file),
                                      preload=True, verbose=False)

        # Fix channel name labels
        eeg_dat.info['ch_names'] = [chl[2:] for chl in \
            eeg_dat.ch_names[:-1]] + [eeg_dat.ch_names[-1]]
        for ind, chi in enumerate(eeg_dat.info['chs']):
            eeg_dat.info['chs'][ind]['ch_name'] = eeg_dat.info['ch_names'][ind]

        # Update channel types
        eeg_dat.set_channel_types(ch_types)

        # Set reference - average reference
        eeg_dat = eeg_dat.set_eeg_reference(ref_channels='average',
                                            projection=False, verbose=False)

        # Set channel montage
        chs = mne.channels.read_montage('standard_1020', eeg_dat.ch_names)
        eeg_dat.set_montage(chs)

        # Get event information & check all used event codes
        evs = mne.find_events(eeg_dat, shortest_event=1, verbose=False)

        # Pull out sampling rate
        srate = eeg_dat.info['sfreq']

        #################################################
        ## Pre-Processing: ICA

        # High-pass filter data for running ICA
        eeg_dat.filter(l_freq=1., h_freq=None, fir_design='firwin')

        if RUN_ICA:

            print("\nICA: CALCULATING SOLUTION\n")

            # ICA settings
            method = 'fastica'
            n_components = 0.99
            random_state = 47
            reject = {'eeg': 20e-4}

            # Initialize ICA object
            ica = ICA(n_components=n_components, method=method,
                      random_state=random_state)

            # Fit ICA
            ica.fit(eeg_dat, reject=reject)

            # Save out ICA solution
            ica.save(pjoin(RES_PATH, 'ICA', subj_label + '-ica.fif'))

        # Otherwise: load previously saved ICA to apply
        else:
            print("\nICA: USING PRECOMPUTED\n")
            ica = read_ica(pjoin(RES_PATH, 'ICA', subj_label + '-ica.fif'))

        # Find components to drop, based on correlation with EOG channels
        drop_inds = []
        for chi in EOG_CHS:
            inds, _ = ica.find_bads_eog(eeg_dat, ch_name=chi, threshold=2.5,
                                             l_freq=1, h_freq=10, verbose=False)
            drop_inds.extend(inds)
        drop_inds = list(set(drop_inds))

        # Set which components to drop, and collect record of this
        ica.exclude = drop_inds
        dropped_components[s_ind, 0:len(drop_inds)] = drop_inds

        # Apply ICA to data
        eeg_dat = ica.apply(eeg_dat)

        #################################################
        ## SORT OUT EVENT CODES

        # Extract a list of all the event labels
        all_trials = [it for it2 in EV_DICT.values() for it in it2]

        # Create list of new event codes to be used to label correct trials (300s)
        all_trials_new = [it + 100 for it in all_trials]
        # This is an annoying way to collapse across the doubled event markers from above
        all_trials_new = [it - 1 if not ind%2 == 0 else it for ind, it in enumerate(all_trials_new)]
        # Get labelled dictionary of new event names
        ev_dict2 = {k:v for k, v in zip(EV_DICT.keys(), set(all_trials_new))}

        # Initialize variables to store new event definitions
        evs2 = np.empty(shape=[0, 3], dtype='int64')
        lags = np.array([])

        # Loop through, creating new events for all correct trials
        t_min, t_max = -0.4, 3.0
        for ref_id, targ_id, new_id in zip(all_trials, CORR_CODES * 6, all_trials_new):

            t_evs, t_lags = mne.event.define_target_events(evs, ref_id, targ_id, srate,
                                                           t_min, t_max, new_id)

            if len(t_evs) > 0:
                evs2 = np.vstack([evs2, t_evs])
                lags = np.concatenate([lags, t_lags])

        #################################################
        ## FOOOF

        # Set channel of interest
        ch_ind = eeg_dat.ch_names.index(CHL)

        # Calculate PSDs over ~ first 2 minutes of data, for specified channel
        fmin, fmax = 1, 50
        tmin, tmax = 5, 125
        psds, freqs = mne.time_frequency.psd_welch(eeg_dat, fmin=fmin, fmax=fmax,
                                                   tmin=tmin, tmax=tmax,
                                                   n_fft=int(2*srate), n_overlap=int(srate),
                                                   n_per_seg=int(2*srate),
                                                   verbose=False)

        # Fit FOOOF across all channels
        fg.fit(freqs, psds, FREQ_RANGE, n_jobs=-1)

        # Save out FOOOF results
        fg.save(subj_label + '_fooof', pjoin(RES_PATH, 'FOOOF'), save_results=True)

        # Extract individualized CF from specified channel, add to group collection
        fm = fg.get_fooof(ch_ind, False)
        fooof_freq, _, _ = get_band_peak(fm.peak_params_, [7, 14])
        group_fooofed_alpha_freqs[s_ind] = fooof_freq

        # If not FOOOF alpha extracted, reset to 10
        if np.isnan(fooof_freq):
            fooof_freq = 10

        #################################################
        ## ALPHA FILTERING

        # CANONICAL: Filter data to canonical alpha band: 8-12 Hz
        alpha_dat = eeg_dat.copy()
        alpha_dat.filter(8, 12, fir_design='firwin', verbose=False)
        alpha_dat.apply_hilbert(envelope=True, verbose=False)

        # FOOOF: Filter data to FOOOF derived alpha band
        fooof_dat = eeg_dat.copy()
        fooof_dat.filter(fooof_freq-2, fooof_freq+2, fir_design='firwin')
        fooof_dat.apply_hilbert(envelope=True)

        #################################################
        ## EPOCH TRIALS

        # Set epoch timings
        tmin, tmax = -0.85, 1.1

        # Epoch trials - raw data for trial rejection
        epochs = mne.Epochs(eeg_dat, evs2, ev_dict2, tmin=tmin, tmax=tmax,
                            baseline=None, preload=True, verbose=False)

        # Epoch trials - filtered version
        epochs_alpha = mne.Epochs(alpha_dat, evs2, ev_dict2, tmin=tmin, tmax=tmax,
                                  baseline=(-0.5, -0.35), preload=True, verbose=False)
        epochs_fooof = mne.Epochs(fooof_dat, evs2, ev_dict2, tmin=tmin, tmax=tmax,
                                  baseline=(-0.5, -0.35), preload=True, verbose=False)

        #################################################
        ## PRE-PROCESSING: AUTO-REJECT
        if RUN_AUTOREJECT:

            print('\nAUTOREJECT: CALCULATING SOLUTION\n')

            # Initialize and run autoreject across epochs
            ar = AutoReject(n_jobs=4, verbose=False)
            ar.fit(epochs)

            # Save out AR solution
            ar.save(pjoin(RES_PATH, 'AR', subj_label + '-ar.hdf5'), overwrite=True)

        # Otherwise: load & apply previously saved AR solution
        else:
            print('\nAUTOREJECT: USING PRECOMPUTED\n')
            ar = read_auto_reject(pjoin(RES_PATH, 'AR', subj_label + '-ar.hdf5'))
            ar.verbose = 'tqdm'

        # Apply autoreject to the original epochs object it was learnt on
        epochs, rej_log = ar.transform(epochs, return_log=True)

        # Apply autoreject to the copies of the data - apply interpolation, then drop same epochs
        _apply_interp(rej_log, epochs_alpha, ar.threshes_, ar.picks_, ar.verbose)
        epochs_alpha.drop(rej_log.bad_epochs)
        _apply_interp(rej_log, epochs_fooof, ar.threshes_, ar.picks_, ar.verbose)
        epochs_fooof.drop(rej_log.bad_epochs)

        # Collect which epochs were dropped
        dropped_trials[s_ind, 0:sum(rej_log.bad_epochs)] = np.where(rej_log.bad_epochs)[0]

        #################################################
        ## SET UP CHANNEL CLUSTERS

        # Set channel clusters - take channels contralateral to stimulus presentation
        #  Note: channels will be used to extract data contralateral to stimulus presentation
        le_chs = ['P3', 'P5', 'P7', 'P9', 'O1', 'PO3', 'PO7']       # Left Side Channels
        le_inds = [epochs.ch_names.index(chn) for chn in le_chs]
        ri_chs = ['P4', 'P6', 'P8', 'P10', 'O2', 'PO4', 'PO8']      # Right Side Channels
        ri_inds = [epochs.ch_names.index(chn) for chn in ri_chs]

        #################################################
        ## TRIAL-RELATED ANALYSIS: CANONICAL vs. FOOOF

        ## Pull out channels of interest for each load level
        #  Channels extracted are those contralateral to stimulus presentation

        # Canonical Data
        lo1_a = np.concatenate([epochs_alpha['LeLo1']._data[:, ri_inds, :],
                                epochs_alpha['RiLo1']._data[:, le_inds, :]], 0)
        lo2_a = np.concatenate([epochs_alpha['LeLo2']._data[:, ri_inds, :],
                                epochs_alpha['RiLo2']._data[:, le_inds, :]], 0)
        lo3_a = np.concatenate([epochs_alpha['LeLo3']._data[:, ri_inds, :],
                                epochs_alpha['RiLo3']._data[:, le_inds, :]], 0)

        # FOOOFed data
        lo1_f = np.concatenate([epochs_fooof['LeLo1']._data[:, ri_inds, :],
                                epochs_fooof['RiLo1']._data[:, le_inds, :]], 0)
        lo2_f = np.concatenate([epochs_fooof['LeLo2']._data[:, ri_inds, :],
                                epochs_fooof['RiLo2']._data[:, le_inds, :]], 0)
        lo3_f = np.concatenate([epochs_fooof['LeLo3']._data[:, ri_inds, :],
                                epochs_fooof['RiLo3']._data[:, le_inds, :]], 0)

        ## Calculate average across trials and channels - add to group data collection

        # Canonical data
        canonical_group_avg_dat[s_ind, 0, :] = np.mean(lo1_a, 1).mean(0)
        canonical_group_avg_dat[s_ind, 1, :] = np.mean(lo2_a, 1).mean(0)
        canonical_group_avg_dat[s_ind, 2, :] = np.mean(lo3_a, 1).mean(0)

        # FOOOFed data
        fooofed_group_avg_dat[s_ind, 0, :] = np.mean(lo1_f, 1).mean(0)
        fooofed_group_avg_dat[s_ind, 1, :] = np.mean(lo2_f, 1).mean(0)
        fooofed_group_avg_dat[s_ind, 2, :] = np.mean(lo3_f, 1).mean(0)

        #################################################
        ## FOOOFING TRIAL AVERAGED DATA

        # Loop loop loads & trials segments
        for seg_label, seg_time in zip(SEG_LABELS, SEG_TIMES):
            tmin, tmax = seg_time[0], seg_time[1]

            # Calculate PSDs across trials, fit FOOOF models to averages
            for le_label, ri_label, load_label in zip(['LeLo1', 'LeLo2', 'LeLo3'],
                                                      ['RiLo1', 'RiLo2', 'RiLo3'],
                                                      LOAD_LABELS):

                ## Calculate trial wise PSDs for left & right side trials
                trial_freqs, le_trial_psds = periodogram(
                    epochs[le_label]._data[:, :, _time_mask(epochs.times, tmin, tmax, srate)],
                    srate, window='hann', nfft=4*srate)
                trial_freqs, ri_trial_psds = periodogram(
                    epochs[ri_label]._data[:, :, _time_mask(epochs.times, tmin, tmax, srate)],
                    srate, window='hann', nfft=4*srate)

                ## FIT ALL CHANNELS VERSION
                if FIT_ALL_CHANNELS:

                    ## Average spectra across trials within a given load & side
                    le_avg_psd_contra = avg_func(le_trial_psds[:, ri_inds, :], 0)
                    le_avg_psd_ipsi = avg_func(le_trial_psds[:, le_inds, :], 0)
                    ri_avg_psd_contra = avg_func(ri_trial_psds[:, le_inds, :], 0)
                    ri_avg_psd_ipsi = avg_func(ri_trial_psds[:, ri_inds, :], 0)

                    ## Combine spectra across left & right trials for given load
                    ch_psd_contra = np.vstack([le_avg_psd_contra, ri_avg_psd_contra])
                    ch_psd_ipsi = np.vstack([le_avg_psd_ipsi, ri_avg_psd_ipsi])

                    ## Fit FOOOFGroup to all channels, average & and collect results
                    fg.fit(trial_freqs, ch_psd_contra, FREQ_RANGE)
                    fm = avg_fg(fg)
                    fg_dict[load_label]['Contra'][seg_label].append(fm.copy())
                    fg.fit(trial_freqs, ch_psd_ipsi, FREQ_RANGE)
                    fm = avg_fg(fg)
                    fg_dict[load_label]['Ipsi'][seg_label].append(fm.copy())

                ## COLLAPSE ACROSS CHANNELS VERSION
                else:

                    ## Average spectra across trials and channels within a given load & side
                    le_avg_psd_contra = avg_func(avg_func(le_trial_psds[:, ri_inds, :], 0), 0)
                    le_avg_psd_ipsi = avg_func(avg_func(le_trial_psds[:, le_inds, :], 0), 0)
                    ri_avg_psd_contra = avg_func(avg_func(ri_trial_psds[:, le_inds, :], 0), 0)
                    ri_avg_psd_ipsi = avg_func(avg_func(ri_trial_psds[:, ri_inds, :], 0), 0)

                    ## Collapse spectra across left & right trials for given load
                    avg_psd_contra = avg_func(np.vstack([le_avg_psd_contra, ri_avg_psd_contra]), 0)
                    avg_psd_ipsi = avg_func(np.vstack([le_avg_psd_ipsi, ri_avg_psd_ipsi]), 0)

                    ## Fit FOOOF, and collect results
                    fm.fit(trial_freqs, avg_psd_contra, FREQ_RANGE)
                    fg_dict[load_label]['Contra'][seg_label].append(fm.copy())
                    fm.fit(trial_freqs, avg_psd_ipsi, FREQ_RANGE)
                    fg_dict[load_label]['Ipsi'][seg_label].append(fm.copy())

    #################################################
    ## SAVE OUT RESULTS

    # Save out group data
    np.save(pjoin(RES_PATH, 'Group', 'alpha_freqs_group'), group_fooofed_alpha_freqs)
    np.save(pjoin(RES_PATH, 'Group', 'canonical_group'), canonical_group_avg_dat)
    np.save(pjoin(RES_PATH, 'Group', 'fooofed_group'), fooofed_group_avg_dat)
    np.save(pjoin(RES_PATH, 'Group', 'dropped_trials'), dropped_trials)
    np.save(pjoin(RES_PATH, 'Group', 'dropped_components'), dropped_components)

    # Save out second round of FOOOFing
    for load_label in LOAD_LABELS:
        for side_label in SIDE_LABELS:
            for seg_label in SEG_LABELS:
                fg = combine_fooofs(fg_dict[load_label][side_label][seg_label])
                fg.save('Group_' + load_label + '_' + side_label + '_' + seg_label,
                        pjoin(RES_PATH, 'FOOOF'), save_results=True)
Exemplo n.º 26
0
def main():

    # Initialize fg
    # TODO: add any settings we want to ue
    fg = FOOOFGroup(peak_width_limits=[1, 6],
                    min_peak_amplitude=0.075,
                    max_n_peaks=6,
                    peak_threshold=1,
                    verbose=False)

    # Save out a settings file
    fg.save(file_name=GROUP + '_fooof_group_settings',
            file_path=SAVE_PATH,
            save_settings=True)

    # START LOOP
    for sub in SUBJ_DAT_NUM:

        print('Current Subject' + str(sub))

        # load subject data
        subj_dat_fname = str(sub) + "_resampled.set"
        full_path = os.path.join(BASE_PATH, subj_dat_fname)
        path_check = Path(full_path)

        if path_check.is_file():

            eeg_dat = mne.io.read_raw_eeglab(full_path,
                                             event_id_func=None,
                                             preload=True)
            evs = mne.io.eeglab.read_events_eeglab(full_path, EV_DICT)

            new_evs = np.empty(shape=(0, 3))

            for ev_label in BLOCK_EVS:
                ev_code = EV_DICT[ev_label]
                temp = evs[evs[:, 2] == ev_code]
                new_evs = np.vstack([new_evs, temp])

            eeg_dat.add_events(new_evs)

            # set EEG average reference
            eeg_dat.set_eeg_reference()

            ## PRE-PROCESSING: ICA
            if RUN_ICA:

                # ICA settings
                method = 'fastica'
                n_components = 0.99
                random_state = 47
                reject = {'eeg': 20e-4}

                # Initialize ICA object
                ica = ICA(n_components=n_components,
                          method=method,
                          random_state=random_state)

                # High-pass filter data for running ICA
                eeg_dat.filter(l_freq=1., h_freq=None, fir_design='firwin')

                # Fit ICA
                ica.fit(eeg_dat, reject=reject)

                # Find components to drop, based on correlation with EOG channels
                drop_inds = []
                for chi in EOG_CHS:
                    inds, scores = ica.find_bads_eog(eeg_dat,
                                                     ch_name=chi,
                                                     threshold=2.5,
                                                     l_freq=1,
                                                     h_freq=10,
                                                     verbose=False)
                    drop_inds.extend(inds)
                drop_inds = list(set(drop_inds))

                # Set which components to drop, and collect record of this
                ica.exclude = drop_inds
                #dropped_components[s_ind, 0:len(drop_inds)] = drop_inds

                # Save out ICA solution
                ica.save(pjoin(ICA_PATH, str(sub) + '-ica.fif'))

                # Apply ICA to data
                eeg_dat = ica.apply(eeg_dat)

            ## EPOCH BLOCKS
            events = mne.find_events(eeg_dat)

            #epochs = mne.Epochs(eeg_dat, events=events, tmin=5, tmax=125, baseline=None, preload=True)
            rest_epochs = mne.Epochs(eeg_dat,
                                     events=events,
                                     event_id=REST_EVENT_ID,
                                     tmin=5,
                                     tmax=125,
                                     baseline=None,
                                     preload=True)
            trial_epochs = mne.Epochs(eeg_dat,
                                      events=events,
                                      event_id=TRIAL_EVENT_ID,
                                      tmin=5,
                                      tmax=125,
                                      baseline=None,
                                      preload=True)

            ## PRE-PROCESSING: AUTO-REJECT
            if RUN_AUTOREJECT:

                # Initialize and run autoreject across epochs
                ar = AutoReject(n_jobs=4, verbose=False)
                epochs, rej_log = ar.fit_transform(epochs, True)

                # Drop same trials from filtered data
                rest_epochs.drop(rej_log.bad_epochs)
                trial_epochs.drop(rej_log.bad_epochs)

                # Collect list of dropped trials
                dropped_trials[s_ind, 0:sum(rej_log.bad_epochs)] = np.where(
                    rej_log.bad_epochs)[0]

            # Set montage
            chs = mne.channels.read_montage('standard_1020',
                                            rest_epochs.ch_names[:-1])
            rest_epochs.set_montage(chs)
            trial_epochs.set_montage(chs)

            # Calculate PSDs
            rest_psds, rest_freqs = mne.time_frequency.psd_welch(rest_epochs,
                                                                 fmin=1.,
                                                                 fmax=50.,
                                                                 n_fft=2000,
                                                                 n_overlap=250,
                                                                 n_per_seg=500)
            trial_psds, trial_freqs = mne.time_frequency.psd_welch(
                trial_epochs,
                fmin=1.,
                fmax=50.,
                n_fft=2000,
                n_overlap=250,
                n_per_seg=500)

            # Setting frequency range
            freq_range = [3, 30]

            ## FOOOF the Data

            # Rest Data
            for ind, entry in enumerate(rest_psds):
                rest_fooof_psds = rest_psds[ind, :, :]
                fg.fit(rest_freqs, rest_fooof_psds, freq_range)
                fg.save(file_name=str(sub) + 'fooof_group_results' + str(ind),
                        file_path=REST_SAVE_PATH,
                        save_results=True)

            # Trial Data
            for ind, entry in enumerate(trial_psds):
                trial_fooof_psds = trial_psds[ind, :, :]
                fg.fit(trial_freqs, trial_fooof_psds, freq_range)
                fg.save(file_name=str(sub) + 'fooof_group_results' + str(ind),
                        file_path=TRIAL_SAVE_PATH,
                        save_results=True)

            print('Subject Saved')

        else:

            print('Current Subject' + str(sub) + ' does not exist')
            print(path_check)

    print('Pre-processing Complete')
Exemplo n.º 27
0
###################################################################################################

# Initialize a FOOOFGroup object, with desired settings
fg = FOOOFGroup(peak_width_limits=[1, 6],
                min_peak_height=0.15,
                peak_threshold=2.,
                max_n_peaks=6,
                verbose=False)

# Define the frequency range to fit
freq_range = [1, 30]

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

# Fit the power spectrum model across all channels
fg.fit(freqs, spectra, freq_range)

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

# Check the overall results of the group fits
fg.plot()

###################################################################################################
# Plotting Topographies
# ---------------------
#
# Now that we have our power spectrum models calculated across all channels,
# let's start by plotting topographies of some of the resulting model parameters.
#
# To do so, we can leverage the fact that both MNE and FOOOF objects preserve data order.
# So, when we calculated power spectra, our output spectra kept the channel order
Exemplo n.º 28
0
def main(argv):

    # define data and result paths
    basepath = '/Users/rdgao/Documents/data/NeuroTycho/'
    result_basepath = '/Users/rdgao/Documents/code/research/field-echos/results/NeuroTycho/rest_anes/'

    datasets = [
        'Propofol/20120730PF_Anesthesia+and+Sleep_Chibi_Toru+Yanagawa_mat_ECoG128',
        'Propofol/20120731PF_Anesthesia+and+Sleep_George_Toru+Yanagawa_mat_ECoG128',
        'Propofol/20120802PF_Anesthesia+and+Sleep_Chibi_Toru+Yanagawa_mat_ECoG128',
        'Propofol/20120803PF_Anesthesia+and+Sleep_George_Toru+Yanagawa_mat_ECoG128',
        'Ketamine/20120719KT_Anesthesia+and+Sleep_Chibi_Toru+Yanagawa_mat_ECoG128',
        'Ketamine/20120724KT_Anesthesia+and+Sleep_George_Toru+Yanagawa_mat_ECoG128',
        'Ketamine/20120810KT_Anesthesia+and+Sleep_George_Toru+Yanagawa_mat_ECoG128',
        'Ketamine/20120813KT_Anesthesia+and+Sleep_Chibi_Toru+Yanagawa_mat_ECoG128'
    ]
    sess_append = '/Session%d/'
    session_indices = [(1, 0, 1), (1, 2, 3), (2, 0, 1), (2, 1, 2)]
    session_labels = ['EyesOpen', 'EyesClosed', 'Delivery', 'Anesthesia']

    if 'do_psds' in argv:
        for ds in datasets:
            print('------\n', ds)
            for i in range(len(session_indices)):
                session = session_indices[i]
                outfile = str(i) + '_' + (session_labels[i] + '_' +
                                          ds).replace('/', '_').replace(
                                              '+', '_')
                print(outfile)

                # grab ECoG data
                indices = access_nt.get_cond(data_path + ds + sess_append,
                                             session[0], session[1],
                                             session[2])
                data = access_nt.get_ECoG(data_path + ds + sess_append,
                                          session[0], range(1, 129), indices)
                fs = 1000.

                # compute PSDs
                psd_path = result_basepath + outfile + '/psd/'

                # 1Hz resolution psd
                saveout_path = utils.makedir(psd_path,
                                             '/1sec/',
                                             timestamp=False)
                nperseg, noverlap, f_lim, spg_outlier_pct = int(fs), int(
                    fs / 2), 200., 5
                f_axis, psd_mean = ndsp.spectral.compute_spectrum(
                    data,
                    fs,
                    method='mean',
                    nperseg=nperseg,
                    noverlap=noverlap,
                    f_lim=f_lim,
                    spg_outlier_pct=spg_outlier_pct)
                f_axis, psd_med = ndsp.spectral.compute_spectrum(
                    data,
                    fs,
                    method='median',
                    nperseg=nperseg,
                    noverlap=noverlap,
                    f_lim=f_lim,
                    spg_outlier_pct=spg_outlier_pct)
                save_dict = dict((name, eval(name)) for name in [
                    'f_axis', 'psd_mean', 'psd_med', 'nperseg', 'noverlap',
                    'fs', 'spg_outlier_pct'
                ])
                np.savez(file=saveout_path + 'psd.npz', **save_dict)

                # 0.2Hz resolution psd
                saveout_path = utils.makedir(psd_path,
                                             '/5sec/',
                                             timestamp=False)
                nperseg, noverlap, f_lim, spg_outlier_pct = int(fs * 5), int(
                    fs * 4), 200., 5
                f_axis, psd_mean = ndsp.spectral.compute_spectrum(
                    data,
                    fs,
                    method='mean',
                    nperseg=nperseg,
                    noverlap=noverlap,
                    f_lim=f_lim,
                    spg_outlier_pct=spg_outlier_pct)
                f_axis, psd_med = ndsp.spectral.compute_spectrum(
                    data,
                    fs,
                    method='median',
                    nperseg=nperseg,
                    noverlap=noverlap,
                    f_lim=f_lim,
                    spg_outlier_pct=spg_outlier_pct)
                save_dict = dict((name, eval(name)) for name in [
                    'f_axis', 'psd_mean', 'psd_med', 'nperseg', 'noverlap',
                    'fs', 'spg_outlier_pct'
                ])
                np.savez(file=saveout_path + 'psd.npz', **save_dict)

    if 'do_fooof' in argv:
        fooof_settings = [['knee', 3, (1, 70)], ['fixed', 3, (1, 70)],
                          ['fixed', 1, (1, 10)], ['fixed', 1, (30, 70)]]

        session_resultpath = [
            result_basepath + f + '/' for f in os.listdir(result_basepath)
            if os.path.isdir(result_basepath + f)
        ]
        print('FOOOFing...')
        for s in session_resultpath:
            for psd_win in ['1sec/', '5sec/']:
                psd_folder = s + '/psd/' + psd_win
                psd_data = np.load(psd_folder + 'psd.npz')
                for f_s in fooof_settings:
                    # fit to mean and median psd
                    for psd_mode in ['psd_mean', 'psd_med']:
                        fg = FOOOFGroup(aperiodic_mode=f_s[0],
                                        max_n_peaks=f_s[1])
                        fg.fit(psd_data['f_axis'],
                               psd_data[psd_mode],
                               freq_range=f_s[2])
                        fooof_savepath = utils.makedir(psd_folder,
                                                       '/fooof/' + psd_mode +
                                                       '/',
                                                       timestamp=False)
                        fg.save('fg_%s_%ipks_%i-%iHz' %
                                (f_s[0], f_s[1], f_s[2][0], f_s[2][1]),
                                fooof_savepath,
                                save_results=True,
                                save_settings=True)

    print('Done.')
Exemplo n.º 29
0
        allexps = []
        alloffset = []
        if not (j > (i + 2)):
            pass
        else:
            for k in range(1, patientcount + 1):
                freqs = freq_nparray[k - 1]
                psds = psds_nparray[k - 1]
                # ^Note: this also explicitly enforces type as float (type casts to float64, instead of float32)
                #  This is not strictly necessary for fitting, but is for saving out as json from FOOOF, if you want to do that
                fg = FOOOFGroup(peak_threshold=15,
                                peak_width_limits=[3.0, 14.0
                                                   ])  #, aperiodic_mode='knee'
                #fg.report(freqs, psds, [1, 290])
                #fg.fit(freqs,psds,[0.2,290])
                fg.fit(freqs, psds,
                       [i, j])  #this was all i could think of... ;_;
                #fg.plot()

                #reportname = str(k) + '_indiv result'
                #fg.save_report(reportname)

                #print(fg.group_results)

                exps = fg.get_params('aperiodic_params', 'exponent')
                allexps.append(exps)

                offset = fg.get_params('aperiodic_params', 'offset')
                alloffset.append(offset)
            #ok, so for each range, we have 16 sets ofx exponents and 16 sets of y offsets.
            exp_r2 = 0
            off_r2 = 0
Exemplo n.º 30
0
def main():

    ## Individual Model Plot

    # Download examples data files needed for this example
    freqs = load_fooof_data('freqs.npy', folder='data')
    spectrum = load_fooof_data('spectrum.npy', folder='data')

    # Initialize and fit an example power spectrum model
    fm = FOOOF(peak_width_limits=[1, 6],
               max_n_peaks=6,
               min_peak_height=0.2,
               verbose=False)
    fm.fit(freqs, spectrum, [3, 40])

    # Save out the report
    fm.save_report('FOOOF_report.png', 'img')

    ## Group Plot

    # Download examples data files needed for this example
    freqs = load_fooof_data('group_freqs.npy', folder='data')
    spectra = load_fooof_data('group_powers.npy', folder='data')

    # Initialize and fit a group of example power spectrum models
    fg = FOOOFGroup(peak_width_limits=[1, 6],
                    max_n_peaks=6,
                    min_peak_height=0.2,
                    verbose=False)
    fg.fit(freqs, spectra, [3, 30])

    # Save out the report
    fg.save_report('FOOOFGroup_report.png', 'img')

    ## Make the icon plot

    # Simulate an example power spectrum
    fs, ps = gen_power_spectrum([4, 35], [0, 1],
                                [[10, 0.3, 1], [22, 0.15, 1.25]],
                                nlv=0.01)

    def custom_style(ax, log_freqs, log_powers):
        """Custom styler-function for the icon plot."""

        # Set the top and right side frame & ticks off
        ax.spines['right'].set_visible(False)
        ax.spines['top'].set_visible(False)

        # Set linewidth of remaining spines
        ax.spines['left'].set_linewidth(10)
        ax.spines['bottom'].set_linewidth(10)
        ax.set_xticks([], [])
        ax.set_yticks([], [])

    # Create and save out the plot
    plot_spectrum(fs,
                  ps,
                  log_freqs=False,
                  log_powers=True,
                  lw=12,
                  alpha=0.8,
                  color='grey',
                  plot_style=custom_style,
                  ax=check_ax(None, [6, 6]))
    plt.tight_layout()
    plt.savefig('img/spectrum.png')

    ## Clean Up

    # Remove the data folder
    shutil.rmtree('data')