-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpreproc.py
306 lines (255 loc) · 13.2 KB
/
preproc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# J.Dirani
# epochs rejection based on log files not included
# ----------File structure-----------#
# ROOT>
# MRI>
# subjs
# MEG>
# subjs
# STC>
import mne, eelbrain, os, glob, pickle
import numpy as np
import pandas as pd
from os.path import join
%gui qt
mne.set_log_level(verbose='WARNING')
#=========Edit here=========#
expt = 'TwoTones' #experiment name as written on the -raw.fif
ROOT = '/Users/my_user/data_file/'
subjects_dir = os.path.join(ROOT, 'MRI')
subjects = [i for i in os.listdir(ROOT+'MEG') if i.startswith('A0')]
event_id = dict(hi=223, lo=191) #conditions associated with each trigger
os.chdir(ROOT) #setting current dir
epoch_tmin = -0.1
epoch_tmax = 0.6
epoch_baseline = (-0.1,0)
decim = 1
equalize_epochs = False
expected_nb_events = 136
photodiode_realignment = True
SNR = 3 # 3 for ANOVAs, 2 for single trial analyses
fixed = False # False for orientation free, True for fixed orientation
#===========================#
'''==========================================================================='''
''' PART 1: Filter, bads, ICA '''
'''==========================================================================='''
# ------------------ Check which subj dont have ICA files --------------------- #
#Looks for a ..._ICA-raw.fif file. Post ICA+filtered data must be named accordingly
#Not necessary, just a quick way to check how many ICAs are left before running the loops
No_ica=[]
for subj in subjects:
if os.path.isfile('MEG/%s/%s_%s_ICA-raw.fif'%(subj, subj, expt)):
print 'ICA and filtering already done for subj=%s'%subj
else:
No_ica.append(subj)
print ">> ICA not done for %s (%s)" %(No_ica, len(No_ica))
# ----------------------------------- ICA ------------------------------------ #
# compute and save ICA
for subj in subjects:
print subj
if not os.path.isfile('MEG/%s/%s-ica.fif'%(subj,subj)):
print 'importing raw...'
raw = mne.io.read_raw_fif('MEG/%s/%s_%s-raw.fif' %(subj, subj, expt), preload=True)
raw.filter(0,40, method='iir')
ica = mne.preprocessing.ICA(n_components=0.95, method='fastica')
print 'fitting ica...'
# reject = dict(mag=2e-12) # Use this in ica.fit if too mnoisy
ica.fit(raw) #reject=reject
ica.save('MEG/%s/%s-ica.fif'%(subj,subj))
del raw, ica
# Plot to make rejections
for subj in subjects:
print subj
if not os.path.isfile('MEG/%s/%s_%s_ICA-raw.fif' %(subj,subj, expt)):
raw = mne.io.read_raw_fif('MEG/%s/%s_%s-raw.fif' %(subj, subj, expt), preload=True)
raw.filter(0,40, method='iir')
ica = mne.preprocessing.read_ica('MEG/%s/%s-ica.fif'%(subj,subj))
ica.plot_sources(raw)
raw_input('Press enter to continue')
print 'Saving...'
raw = ica.apply (raw, exclude=ica.exclude)
raw.save('MEG/%s/%s_%s_ICA-raw.fif' %(subj,subj, expt))
print 'Saving...'
del raw, ica
'''==========================================================================='''
''' PART 2: get epochs '''
'''==========================================================================='''
for subj in subjects:
print '>> Getting epochs: subj=%s'%subj
if os.path.isfile('MEG/%s/%s-epo.fif' %(subj,subj)):
print '>> EPOCHS ALREADY CREATED FOR SUBJ=%s'%subj
else:
print "%s: Importing filtered+ICA data" %subj
raw = mne.io.read_raw_fif('MEG/%s/%s_%s_ICA-raw.fif' %(subj, subj, expt), preload=True)
#-----------------------------Find events------------------------------#
print "%s: Finding events..." %subj
events = mne.find_events(raw,min_duration=0.002)
assert(len(events) == expected_nb_events)
picks_meg = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False)
#-----------------------Fix photodiode shift---------------------------#
if photodiode_realignment == True:
photodiode = mne.find_events(raw,stim_channel='MISC 010',min_duration=0.005)
if len(events) != len(photodiode):
raise ValueError('Length of photodiode and events dont match.')
delays = []
for i in range(len(events)):
delay = photodiode[i][0] - events[i][0]
delays.append(delay)
raw_input('Average photodiode delay = %s. Ok?' %(np.mean(delays)))
print 'Realigning events...'
for i in range(len(events)):
events[i][0] = photodiode[i][0]
#----------------------Reject epochs based on logs---------------------#
# print "Rejecting epochs based on logs"
# logfile_dir = 'MEG/%s/initial_output/%s_log_mask.csv' %(subj,subj)
# logfile = pd.read_csv(logfile_dir)
# logfile['epochs_mask'] = np.where(logfile['mask']==1, True, False)
#
epochs = mne.Epochs(raw, events, event_id=event_id, tmin=epoch_tmin, tmax=epoch_tmax, baseline=epoch_baseline, picks=picks_meg, decim=decim, preload=True)
#
# epochs = epochs[logfile.ep_mask]
# del logfile
#----------------------Manual epochs rejection-------------------------#
print ">> Epochs rejection for subj=%s" %subj
if os.path.isfile('MEG/%s/%s_rejfile.pickled' %(subj, subj)):
print 'Rejections file for %s exists, loading file...' %(subj)
rejfile = eelbrain.load.unpickle('MEG/%s/%s_rejfile.pickled' %(subj, subj))
rejs = rejfile['accept'].x
epochs_rej=epochs[rejs]
print 'Done.'
else:
print 'Rejections file for %s does not exist, opening GUI...' %(subj)
eelbrain.gui.select_epochs(epochs, vlim=2e-12, mark=['MEG 087','MEG 130'])
raw_input('NOTE: Save as MEG/%s/%s_rejfile.pickled. \nPress enter when you are done rejecting epochs in the GUI...'%(subj,subj))
# Marking bad channels
bad_channels = raw_input('\nMarking bad channels:\nWrite bad channels separated by COMMA (e.g. MEG 017, MEG 022)\nIf no bad channels, press enter\n>')
if bad_channels == '':
del bad_channels
else:
bad_channels = bad_channels.split(', ')
epochs.interpolate_bads(bad_channels)
del bad_channels
# Reject marked epochs
rejfile = eelbrain.load.unpickle('MEG/%s/%s_rejfile.pickled' %(subj, subj))
rejs = rejfile['accept'].x
epochs_rej = epochs[rejs]
# equalize events
if equalize_epochs == True:
print "equalizing epochs..."
len_epochs_rej = len(epochs_rej) #because epochs_rej will be overwritten. Need this to later log to info.csv
epochs_eq, eq_ids = epochs_rej.equalize_event_counts(event_id) #ids used later to log into info.csv
else:
print "not equalizing epochs."
epochs_eq = epochs_rej.copy()
eq_ids = []
len_epochs_rej = len(epochs_rej)
print '%s: bad epochs rejected' %subj
#------------------Save raw.info and epochs to file-------------------#
print 'Saving epochs to file...'
info = raw.info
pickle.dump(info, open('MEG/%s/%s-info.pickled' %(subj,subj), 'wb'))
epochs_eq.save('MEG/%s/%s-epo.fif' %(subj,subj))
# write rejection info to csv
nb_accuracy_rej = np.unique(accuracy_mask, return_counts=True)[1][0]
nb_noise_rej = np.unique(rejs, return_counts=True)[1][0]
with open('MEG/%s/info/rej_info.csv'%subj, 'w') as f:
f.write('accuracy_rej,noise_rej,good,equalize_counts,equalize_dropped,remaining_after_equalize\n')
f.write('%s,%s,%s,%s,%s,%s\n'%(nb_accuracy_rej, nb_noise_rej, len_epochs_rej, equalize_epochs, len(eq_ids),len(epochs_eq)))
f.close()
# Write epochs counts per condition to csv
with open('MEG/%s/info/epo_count.csv'%subj, 'w') as f:
for cond in event_id.keys():
f.write('%s,%s\n'%(cond, len(epochs_eq[cond])))
f.close()
del raw
print 'Done.'
'''==========================================================================='''
''' PART 3: Create STCs '''
'''==========================================================================='''
for subj in subjects:
if os.path.exists('STC/%s'%subj):
print 'STCs ALREADY CREATED FOR SUBJ = %s' %subj
else:
print ">> STCs for subj=%s:"%subj
print 'Importing data...'
info = pickle.load(open('MEG/%s/%s-info.pickled' %(subj,subj), 'rb'))
epochs_rej = mne.read_epochs('MEG/%s/%s-epo.fif' %(subj,subj))
trans = mne.read_trans('MEG/%s/%s-trans.fif' %(subj,subj))
bem_fname = join(subjects_dir, '%s/bem/%s-inner_skull-bem-sol.fif'%(subj,subj))
src_fname = join(subjects_dir, '%s/bem/%s-ico-4-src.fif' %(subj,subj))
fwd_fname = 'MEG/%s/%s-fwd.fif' %(subj, subj)
cov_fname = 'MEG/%s/%s-cov.fif' %(subj,subj)
#---------------------------get evoked------------------------------------#
print '%s: Creating evoked responses' %subj
evoked = []
conditions = event_id.keys()
for cond in conditions:
evoked.append(epochs_rej[cond].average())
print 'Done.'
# Sanity check: plot evoked
if not os.path.isdir('sanity_check/evoked/'):
os.makedirs('sanity_check/evoked/')
all_evokeds = mne.combine_evoked(evoked, weights='equal')
evoked_plot = all_evokeds.plot_joint(show=False)
evoked_plot.savefig('sanity_check/evoked/%s_evoked.png'%subj)
#----------------------Source space---------------------------#
print 'Generating source space...'
if os.path.isfile(src_fname):
print 'src for subj = %s already exists, loading file...' %subj
src = mne.read_source_spaces(fname=src_fname)
print 'Done.'
else:
print 'src for subj = %s does not exist, creating file...' %subj
src = mne.setup_source_space(subject=subj, spacing='ico4', subjects_dir=subjects_dir)
src.save(src_fname, overwrite=True)
print 'Done. File saved.'
#-------------------------- BEM ------------------------------#
if not os.path.isfile(bem_fname):
print 'BEM for subj=%s does not exists, creating...' %subj
conductivity = (0.3,) # for single layer
model = mne.make_bem_model(subject=subj, ico=4, conductivity=conductivity, subjects_dir=subjects_dir)
bem = mne.make_bem_solution(model)
mne.write_bem_solution(bem_fname, bem)
#--------------------Forward solution-------------------------#
print 'Creating forward solution...'
if os.path.isfile(fwd_fname):
print 'forward soltion for subj=%s exists, loading file.' %subj
fwd = mne.read_forward_solution(fwd_fname)
print 'Done.'
else:
print 'forward soltion for subj=%s does not exist, creating file.' %subj
fwd = mne.make_forward_solution(info=info, trans=trans, src=src, bem=bem_fname, ignore_ref=True)
mne.write_forward_solution(fwd_fname, fwd)
print 'Done. File saved.'
#----------------------Covariance------------------------------#
print 'Getting covariance'
if os.path.isfile(cov_fname):
print 'cov for subj=%s exists, loading file...' %subj
cov = mne.read_cov(cov_fname)
print 'Done.'
else:
print 'cov for subj=%s does not exist, creating file...' %subj
cov = mne.compute_covariance(epochs_rej,tmin=None,tmax=0, method=['shrunk', 'diagonal_fixed', 'empirical'])
cov.save(cov_fname)
print 'Done. File saved.'
#---------------------Inverse operator-------------------------#
print 'Getting inverse operator'
if fixed == True:
fwd = mne.convert_forward_solution(fwd, surf_ori=True)
inv = mne.minimum_norm.make_inverse_operator(info, fwd, cov, depth=None, loose=None, fixed=fixed) #fixed=False: Ignoring dipole direction.
lambda2 = 1.0 / SNR ** 2.0
#--------------------------STCs--------------------------------#
print '%s: Creating STCs...'%subj
os.makedirs('STC/%s' %subj)
for ev in evoked:
stc = mne.minimum_norm.apply_inverse(ev, inv, lambda2=lambda2, method='dSPM')
# mophing stcs to the fsaverage using precomputed matrix method:
vertices_to = mne.grade_to_vertices('fsaverage', grade=4, subjects_dir=subjects_dir) #fsaverage's source space
morph_mat = mne.compute_morph_matrix(subject_from=subj, subject_to='fsaverage', vertices_from=stc.vertices, vertices_to=vertices_to, subjects_dir=subjects_dir)
stc_morph = mne.morph_data_precomputed(subject_from=subj, subject_to='fsaverage', stc_from=stc, vertices_to=vertices_to, morph_mat=morph_mat)
stc_morph.save('STC/%s/%s_%s_dSPM' %(subj,subj,ev.comment))
del stc, stc_morph
print '>> DONE CREATING STCS FOR SUBJ=%s'%subj
print '-----------------------------------------\n'
#deleting variables
del epochs_rej, evoked, info, trans, src, fwd, cov, inv