|
| 1 | +""" |
| 2 | +Cueing Group Analysis Winter 2019 |
| 3 | +=============================== |
| 4 | +
|
| 5 | +""" |
| 6 | + |
| 7 | +################################################################################################### |
| 8 | +# Setup |
| 9 | +# ----------------------------- |
| 10 | + |
| 11 | +# Standard Pythonic imports |
| 12 | +import os,sys,glob,numpy as np, pandas as pd |
| 13 | +import scipy |
| 14 | +from collections import OrderedDict |
| 15 | +import warnings |
| 16 | +warnings.filterwarnings('ignore') |
| 17 | +from matplotlib import pyplot as plt |
| 18 | +import matplotlib.patches as patches |
| 19 | + |
| 20 | +# MNE functions |
| 21 | +from mne import Epochs, find_events, concatenate_raws |
| 22 | +from mne.time_frequency import tfr_morlet |
| 23 | + |
| 24 | +# EEG-Noteooks functions |
| 25 | +from eegnb.analysis.analysis_utils import load_data |
| 26 | +from eegnb.datasets import fetch_dataset |
| 27 | + |
| 28 | +# sphinx_gallery_thumbnail_number = 1 |
| 29 | + |
| 30 | +################################################################################################### |
| 31 | +# Load the data |
| 32 | +# ----------------------------- |
| 33 | + |
| 34 | +eegnb_data_path = os.path.join(os.path.expanduser('~/'),'.eegnb', 'data') |
| 35 | +cueing_data_path = os.path.join(eegnb_data_path, 'visual-cueing', 'kylemathlab_dev') |
| 36 | + |
| 37 | +# If dataset hasn't been downloaded yet, download it |
| 38 | +if not os.path.isdir(cueing_data_path): |
| 39 | + fetch_dataset(data_dir=eegnb_data_path, experiment='visual-cueing', site='kylemathlab_dev') |
| 40 | + |
| 41 | + |
| 42 | +################################################################################################### |
| 43 | +# Put the data into MNE Epochs |
| 44 | +# ----------------------------- |
| 45 | +# |
| 46 | +# Fall 2018 |
| 47 | +# subs = [101, 102, 103, 104, 105, 106, 108, 109, 110, 111, 112, |
| 48 | +# 202, 203, 204, 205, 207, 208, 209, 210, 211, |
| 49 | +# 301, 302, 303, 304, 305, 306, 307, 308, 309] |
| 50 | +# |
| 51 | +# Winter 2019 |
| 52 | +subs = [1101, 1102, 1103, 1104, 1105, 1106, 1108, 1109, 1110, |
| 53 | + 1202, 1203, 1205, 1206, 1209, 1210, 1211, 1215, |
| 54 | + 1301, 1302, 1313, |
| 55 | + 1401, 1402, 1403, 1404, 1405, 1408, 1410, 1411, 1412, 1413, 1413, 1414, 1415, 1416] |
| 56 | +# |
| 57 | +# Both |
| 58 | +# subs = [101, 102, 103, 104, 105, 106, 108, 109, 110, 111, 112, |
| 59 | +# 202, 203, 204, 205, 207, 208, 209, 210, 211, |
| 60 | +# 301, 302, 303, 304, 305, 306, 307, 308, 309, |
| 61 | +# 1101, 1102, 1103, 1104, 1105, 1106, 1108, 1109, 1110, |
| 62 | +# 1202, 1203, 1205, 1206, 1209, 1210, 1211, 1215, |
| 63 | +# 1301, 1302, 1313, |
| 64 | +# 1401, 1402, 1403, 1404, 1405, 1408, 1410, 1411, 1412, 1413, 1413, 1414, 1415, 1416] |
| 65 | +# |
| 66 | +# |
| 67 | +# placeholders to add to for each subject |
| 68 | +diff_out = [] |
| 69 | +Ipsi_out = [] |
| 70 | +Contra_out = [] |
| 71 | +Ipsi_spectra_out = [] |
| 72 | +Contra_spectra_out = [] |
| 73 | +diff_spectra_out = [] |
| 74 | +ERSP_diff_out = [] |
| 75 | +ERSP_Ipsi_out = [] |
| 76 | +ERSP_Contra_out = [] |
| 77 | + |
| 78 | +frequencies = np.linspace(6, 30, 100, endpoint=True) |
| 79 | +wave_cycles = 6 |
| 80 | + |
| 81 | +# time frequency window for analysis |
| 82 | +f_low = 7 # Hz |
| 83 | +f_high = 10 |
| 84 | +f_diff = f_high-f_low |
| 85 | + |
| 86 | +t_low = 0 # s |
| 87 | +t_high = 1 |
| 88 | +t_diff = t_high-t_low |
| 89 | + |
| 90 | +bad_subs= [6, 7, 13, 26] |
| 91 | +really_bad_subs = [11, 12, 19] |
| 92 | +sub_count = 0 |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | +for sub in subs: |
| 97 | + print(sub) |
| 98 | + |
| 99 | + sub_count += 1 |
| 100 | + |
| 101 | + |
| 102 | + if (sub_count in really_bad_subs): |
| 103 | + rej_thresh_uV = 90 |
| 104 | + elif (sub_count in bad_subs): |
| 105 | + rej_thresh_uV = 90 |
| 106 | + else: |
| 107 | + rej_thresh_uV = 90 |
| 108 | + |
| 109 | + rej_thresh = rej_thresh_uV*1e-6 |
| 110 | + |
| 111 | + |
| 112 | + # Load both sessions |
| 113 | + raw = load_data(sub,1, # subject, session |
| 114 | + experiment='visual-cueing',site='kylemathlab_dev',device_name='muse2016', |
| 115 | + data_dir = eegnb_data_path) |
| 116 | + |
| 117 | + raw.append( |
| 118 | + load_data(sub,2, # subject, session |
| 119 | + experiment='visual-cueing', site='kylemathlab_dev', device_name='muse2016', |
| 120 | + data_dir = eegnb_data_path)) |
| 121 | + |
| 122 | + |
| 123 | + # Filter Raw Data |
| 124 | + raw.filter(1,30, method='iir') |
| 125 | + |
| 126 | + #Select Events |
| 127 | + events = find_events(raw) |
| 128 | + event_id = {'LeftCue': 1, 'RightCue': 2} |
| 129 | + epochs = Epochs(raw, events=events, event_id=event_id, |
| 130 | + tmin=-1, tmax=2, baseline=(-1, 0), |
| 131 | + reject={'eeg':rej_thresh}, preload=True, |
| 132 | + verbose=False, picks=[0, 3]) |
| 133 | + print('Trials Remaining: ' + str(len(epochs.events)) + '.') |
| 134 | + |
| 135 | + # Compute morlet wavelet |
| 136 | + # Left Cue |
| 137 | + tfr, itc = tfr_morlet(epochs['LeftCue'], freqs=frequencies, |
| 138 | + n_cycles=wave_cycles, return_itc=True) |
| 139 | + tfr = tfr.apply_baseline((-1,-.5),mode='mean') |
| 140 | + power_Ipsi_TP9 = tfr.data[0,:,:] |
| 141 | + power_Contra_TP10 = tfr.data[1,:,:] |
| 142 | + |
| 143 | + # Right Cue |
| 144 | + tfr, itc = tfr_morlet(epochs['RightCue'], freqs=frequencies, |
| 145 | + n_cycles=wave_cycles, return_itc=True) |
| 146 | + tfr = tfr.apply_baseline((-1,-.5),mode='mean') |
| 147 | + power_Contra_TP9 = tfr.data[0,:,:] |
| 148 | + power_Ipsi_TP10 = tfr.data[1,:,:] |
| 149 | + |
| 150 | + # Compute averages Differences |
| 151 | + power_Avg_Ipsi = (power_Ipsi_TP9+power_Ipsi_TP10)/2; |
| 152 | + power_Avg_Contra = (power_Contra_TP9+power_Contra_TP10)/2; |
| 153 | + power_Avg_Diff = power_Avg_Ipsi-power_Avg_Contra; |
| 154 | + |
| 155 | + #output data into array |
| 156 | + times = epochs.times |
| 157 | + Ipsi_out.append(np.mean(power_Avg_Ipsi[np.argmax(frequencies>f_low): |
| 158 | + np.argmax(frequencies>f_high)-1, |
| 159 | + np.argmax(times>t_low):np.argmax(times>t_high)-1 ] |
| 160 | + ) |
| 161 | + ) |
| 162 | + Ipsi_spectra_out.append(np.mean(power_Avg_Ipsi[:,np.argmax(times>t_low): |
| 163 | + np.argmax(times>t_high)-1 ],1 |
| 164 | + ) |
| 165 | + ) |
| 166 | + |
| 167 | + Contra_out.append(np.mean(power_Avg_Contra[np.argmax(frequencies>f_low): |
| 168 | + np.argmax(frequencies>f_high)-1, |
| 169 | + np.argmax(times>t_low):np.argmax(times>t_high)-1 ] |
| 170 | + ) |
| 171 | + ) |
| 172 | + |
| 173 | + Contra_spectra_out.append(np.mean(power_Avg_Contra[:,np.argmax(times>t_low): |
| 174 | + np.argmax(times>t_high)-1 ],1)) |
| 175 | + |
| 176 | + |
| 177 | + diff_out.append(np.mean(power_Avg_Diff[np.argmax(frequencies>f_low): |
| 178 | + np.argmax(frequencies>f_high)-1, |
| 179 | + np.argmax(times>t_low):np.argmax(times>t_high)-1 ] |
| 180 | + ) |
| 181 | + ) |
| 182 | + diff_spectra_out.append(np.mean(power_Avg_Diff[:,np.argmax(times>t_low): |
| 183 | + np.argmax(times>t_high)-1 ],1 |
| 184 | + ) |
| 185 | + ) |
| 186 | + |
| 187 | + #save the spectrograms to average over after |
| 188 | + ERSP_diff_out.append(power_Avg_Diff) |
| 189 | + ERSP_Ipsi_out.append(power_Avg_Ipsi) |
| 190 | + ERSP_Contra_out.append(power_Avg_Contra) |
| 191 | + |
| 192 | + |
| 193 | +################################################################################################### |
| 194 | +# Combine subjects |
| 195 | +# ---------------------------- |
| 196 | + |
| 197 | +#average spectrograms |
| 198 | +GrandAvg_diff = np.nanmean(ERSP_diff_out,0) |
| 199 | +GrandAvg_Ipsi = np.nanmean(ERSP_Ipsi_out,0) |
| 200 | +GrandAvg_Contra = np.nanmean(ERSP_Contra_out,0) |
| 201 | + |
| 202 | +#average spectra |
| 203 | +GrandAvg_spec_Ipsi = np.nanmean(Ipsi_spectra_out,0) |
| 204 | +GrandAvg_spec_Contra = np.nanmean(Contra_spectra_out,0) |
| 205 | +GrandAvg_spec_diff = np.nanmean(diff_spectra_out,0) |
| 206 | + |
| 207 | +#error bars for spectra (standard error) |
| 208 | +num_good = len(diff_out) - sum(np.isnan(diff_out)) |
| 209 | +GrandAvg_spec_Ipsi_ste = np.nanstd(Ipsi_spectra_out,0)/np.sqrt(num_good) |
| 210 | +GrandAvg_spec_Contra_ste = np.nanstd(Contra_spectra_out,0)/np.sqrt(num_good) |
| 211 | +GrandAvg_spec_diff_ste = np.nanstd(diff_spectra_out,0)/np.sqrt(num_good) |
| 212 | + |
| 213 | +################################################################################################### |
| 214 | + |
| 215 | +#Plot Spectra error bars |
| 216 | +fig, ax = plt.subplots(1) |
| 217 | +plt.errorbar(frequencies,GrandAvg_spec_Ipsi,yerr=GrandAvg_spec_Ipsi_ste) |
| 218 | +plt.errorbar(frequencies,GrandAvg_spec_Contra,yerr=GrandAvg_spec_Contra_ste) |
| 219 | +plt.legend(('Ipsi','Contra')) |
| 220 | +plt.xlabel('Frequency (Hz)') |
| 221 | +plt.ylabel('Power (uV^2)') |
| 222 | +plt.hlines(0,3,33) |
| 223 | + |
| 224 | +################################################################################################### |
| 225 | + |
| 226 | +#Plot Spectra Diff error bars |
| 227 | +fig, ax = plt.subplots(1) |
| 228 | +plt.errorbar(frequencies,GrandAvg_spec_diff,yerr=GrandAvg_spec_diff_ste) |
| 229 | +plt.legend('Ipsi-Contra') |
| 230 | +plt.xlabel('Frequency (Hz)') |
| 231 | +plt.ylabel('Power (uV^2)') |
| 232 | +plt.hlines(0,3,33) |
| 233 | + |
| 234 | +################################################################################################### |
| 235 | +# |
| 236 | +# Grand Average Ipsi |
| 237 | +plot_max = np.max([np.max(np.abs(GrandAvg_Ipsi)), np.max(np.abs(GrandAvg_Contra))]) |
| 238 | +fig, ax = plt.subplots(1) |
| 239 | +im = plt.imshow(GrandAvg_Ipsi, |
| 240 | + extent=[times[0], times[-1], frequencies[0], frequencies[-1]], |
| 241 | + aspect='auto', origin='lower', cmap='coolwarm', vmin=-plot_max, vmax=plot_max) |
| 242 | +plt.xlabel('Time (sec)') |
| 243 | +plt.ylabel('Frequency (Hz)') |
| 244 | +plt.title('Power Ipsi') |
| 245 | +cb = fig.colorbar(im) |
| 246 | +cb.set_label('Power') |
| 247 | +# Create a Rectangle patch |
| 248 | +rect = patches.Rectangle((t_low,f_low),t_diff,f_diff,linewidth=1,edgecolor='k',facecolor='none') |
| 249 | +# Add the patch to the Axes |
| 250 | +ax.add_patch(rect) |
| 251 | +# |
| 252 | +##e################################################################################################# |
| 253 | +# |
| 254 | +# Grand Average Contra |
| 255 | +# |
| 256 | +fig, ax = plt.subplots(1) |
| 257 | +im = plt.imshow(GrandAvg_Contra, |
| 258 | + extent=[times[0], times[-1], frequencies[0], frequencies[-1]], |
| 259 | + aspect='auto', origin='lower', cmap='coolwarm', vmin=-plot_max, vmax=plot_max) |
| 260 | +plt.xlabel('Time (sec)') |
| 261 | +plt.ylabel('Frequency (Hz)') |
| 262 | +plt.title('Power Contra') |
| 263 | +cb = fig.colorbar(im) |
| 264 | +cb.set_label('Power') |
| 265 | +# Create a Rectangle patch |
| 266 | +rect = patches.Rectangle((t_low,f_low),t_diff,f_diff,linewidth=1,edgecolor='k',facecolor='none') |
| 267 | +# Add the patch to the Axes |
| 268 | +ax.add_patch(rect) |
| 269 | +# |
| 270 | +################################################################################################### |
| 271 | +# |
| 272 | +# Grand Average Ipsi-Contra Difference |
| 273 | +# |
| 274 | +plot_max_diff = np.max(np.abs(GrandAvg_diff)) |
| 275 | +fig, ax = plt.subplots(1) |
| 276 | +im = plt.imshow(GrandAvg_diff, |
| 277 | + extent=[times[0], times[-1], frequencies[0], frequencies[-1]], |
| 278 | + aspect='auto', origin='lower', cmap='coolwarm', vmin=-plot_max_diff, vmax=plot_max_diff) |
| 279 | +plt.xlabel('Time (sec)') |
| 280 | +plt.ylabel('Frequency (Hz)') |
| 281 | +plt.title('Power Difference Ipsi-Contra') |
| 282 | +cb = fig.colorbar(im) |
| 283 | +cb.set_label('Ipsi-Contra Power') |
| 284 | +# Create a Rectangle patch |
| 285 | +rect = patches.Rectangle((t_low,f_low),t_diff,f_diff,linewidth=1,edgecolor='k',facecolor='none') |
| 286 | +# Add the patch to the Axes |
| 287 | +ax.add_patch(rect) |
| 288 | + |
| 289 | +################################################################################################### |
| 290 | +# Compute t test |
| 291 | +# ---------------------------- |
| 292 | + |
| 293 | +num_good = len(diff_out) - sum(np.isnan(diff_out)) |
| 294 | + |
| 295 | +[tstat, pval] = scipy.stats.ttest_ind(diff_out,np.zeros(len(diff_out)),nan_policy='omit') |
| 296 | +print('Ipsi Mean: '+ str(np.nanmean(Ipsi_out))) |
| 297 | +print('Contra Mean: '+ str(np.nanmean(Contra_out))) |
| 298 | +print('Mean Diff: '+ str(np.nanmean(diff_out))) |
| 299 | +print('t(' + str(num_good-1) + ') = ' + str(round(tstat,3))) |
| 300 | +print('p = ' + str(round(pval,3))) |
| 301 | + |
| 302 | +################################################################################################### |
| 303 | +# Save average powers ipsi and contra |
| 304 | +# ---------------------------- |
| 305 | + |
| 306 | +print(diff_out) |
| 307 | +raw_data = {'Ipsi Power': Ipsi_out, |
| 308 | + 'Contra Power': Contra_out} |
| 309 | +df = pd.DataFrame(raw_data, columns = ['Ipsi Power', 'Contra Power']) |
| 310 | +print(df) |
| 311 | +df.to_csv('375CueingEEG.csv') |
| 312 | +print('Saved subject averages for each condition to 375CueingEEG.csv file in present directory') |
| 313 | + |
| 314 | +################################################################################################### |
| 315 | +# Save spectra |
| 316 | +# ---------------------------- |
| 317 | + |
| 318 | +df = pd.DataFrame(Ipsi_spectra_out,columns=frequencies) |
| 319 | +print(df) |
| 320 | +df.to_csv('375CueingIpsiSpec.csv') |
| 321 | + |
| 322 | +df = pd.DataFrame(Contra_spectra_out,columns=frequencies) |
| 323 | +df.to_csv('375CueingContraSpec.csv') |
| 324 | +print('Saved Spectra to 375CueingContraSpec.csv file in present directory') |
| 325 | + |
| 326 | + |
0 commit comments