def compute_cov_from_empty_room(subject, session): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, check=False) raw_er_fname = bids_basename.copy().update(kind=config.get_kind(), task='noise', processing='filt', extension='.fif') cov_fname = bids_basename.copy().update(kind='cov', extension='.fif') extra_params = dict() if not config.use_maxwell_filter and config.allow_maxshield: extra_params['allow_maxshield'] = config.allow_maxshield msg = (f'Computing regularized covariance based on empty-room recording. ' f'Input: {raw_er_fname}, Output: {cov_fname}') logger.info( gen_log_message(message=msg, step=11, subject=subject, session=session)) raw_er = mne.io.read_raw_fif(raw_er_fname, preload=True, **extra_params) cov = mne.compute_raw_covariance(raw_er, method='shrunk', rank='info') cov.save(cov_fname)
def plot_er_psd(subject, session): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, kind=config.get_kind(), task='noise', processing='filt', extension='.fif') extra_params = dict() if not config.use_maxwell_filter and config.allow_maxshield: extra_params['allow_maxshield'] = config.allow_maxshield raw_er_filtered = mne.io.read_raw_fif(bids_basename, preload=True, **extra_params) fmax = 1.5 * config.h_freq if config.h_freq is not None else np.inf fig = raw_er_filtered.plot_psd(fmax=fmax, show=False) return fig
def compute_cov_from_epochs(subject, session, tmin, tmax): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) if config.use_ica or config.use_ssp: extension = '_cleaned-epo' else: extension = '-epo' epo_fname = op.join(deriv_path, bids_basename + '%s.fif' % extension) cov_fname = op.join(deriv_path, bids_basename + '-cov.fif') msg = (f"Computing regularized covariance based on epochs' baseline " f"periods. Input: {epo_fname}, Output: {cov_fname}") logger.info( gen_log_message(message=msg, step=11, subject=subject, session=session)) epochs = mne.read_epochs(epo_fname, preload=True) cov = mne.compute_covariance(epochs, tmin=tmin, tmax=tmax, method='shrunk', rank='info') cov.save(cov_fname)
def plot_events(subject, session, deriv_path): raws_filt = [] bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, recording=config.rec, space=config.space, prefix=deriv_path, kind=config.get_kind(), processing='filt', extension='.fif') for run in config.get_runs(): fname = bids_basename.copy().update(run=run) raw_filt = mne.io.read_raw_fif(fname) raws_filt.append(raw_filt) del fname # Concatenate the filtered raws and extract the events. raw_filt_concat = mne.concatenate_raws(raws_filt) events, event_id = mne.events_from_annotations(raw=raw_filt_concat) fig = mne.viz.plot_events(events=events, event_id=event_id, first_samp=raw_filt_concat.first_samp, sfreq=raw_filt_concat.info['sfreq'], show=False) return fig
def load_data(bids_basename): # read_raw_bids automatically # - populates bad channels using the BIDS channels.tsv # - sets channels types according to BIDS channels.tsv `type` column # - sets raw.annotations using the BIDS events.tsv params = get_entities_from_fname(bids_basename) subject = params['subject'] session = params['session'] extra_params = dict() if config.allow_maxshield: extra_params['allow_maxshield'] = config.allow_maxshield raw = read_raw_bids(bids_basename=bids_basename, bids_root=config.bids_root, extra_params=extra_params, kind=config.get_kind()) if config.daysback is not None: raw.anonymize(daysback=config.daysback) if subject != 'emptyroom': # Crop the data. if config.crop is not None: raw.crop(*config.crop) # Rename events. if config.rename_events: rename_events(raw=raw, subject=subject, session=session) raw.load_data() if hasattr(raw, 'fix_mag_coil_types'): raw.fix_mag_coil_types() montage_name = config.eeg_template_montage if config.get_kind() == 'eeg' and montage_name: msg = (f'Setting EEG channel locatiions to template montage: ' f'{montage_name}.') logger.info(gen_log_message(message=msg, step=1, subject=subject, session=session)) montage = mne.channels.make_standard_montage(montage_name) raw.set_montage(montage, on_missing='warn') return raw
def run_ssp(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) # compute SSP on first run of raw run = config.get_runs()[0] bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=run, recording=config.rec, space=config.space, prefix=deriv_path) # Prepare a name to save the data raw_fname_in = bids_basename.copy().update(processing='filt', kind=config.get_kind(), extension='.fif') # when saving proj, use run=None proj_fname_out = bids_basename.copy().update(run=None, kind='proj', extension='.fif', check=False) msg = f'Input: {raw_fname_in}, Output: {proj_fname_out}' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) raw = mne.io.read_raw_fif(raw_fname_in) # XXX : n_xxx should be options in config msg = 'Computing SSPs for ECG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) ecg_projs, ecg_events = \ compute_proj_ecg(raw, n_grad=1, n_mag=1, n_eeg=0, average=True) msg = 'Computing SSPs for EOG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) eog_projs, eog_events = \ compute_proj_eog(raw, n_grad=1, n_mag=1, n_eeg=1, average=True) mne.write_proj(proj_fname_out, eog_projs + ecg_projs)
def run_evoked(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) if config.use_ica or config.use_ssp: extension = '_cleaned-epo' else: extension = '-epo' fname_in = op.join(deriv_path, bids_basename + '%s.fif' % extension) fname_out = op.join(deriv_path, bids_basename + '-ave.fif') msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( gen_log_message(message=msg, step=6, subject=subject, session=session)) epochs = mne.read_epochs(fname_in, preload=True) msg = 'Creating evoked data based on experimental conditions …' logger.info( gen_log_message(message=msg, step=6, subject=subject, session=session)) evokeds = [] for condition in config.conditions: evoked = epochs[condition].average() evokeds.append(evoked) if config.contrasts: msg = 'Contrasting evoked responses …' logger.info( gen_log_message(message=msg, step=6, subject=subject, session=session)) for contrast in config.contrasts: cond_1, cond_2 = contrast evoked_1 = epochs[cond_1].average() evoked_2 = epochs[cond_2].average() evoked_diff = mne.combine_evoked([evoked_1, evoked_2], weights=[1, -1]) evokeds.append(evoked_diff) mne.evoked.write_evokeds(fname_out, evokeds) if config.interactive: for evoked in evokeds: evoked.plot()
def run_forward(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) fname_evoked = op.join(deriv_path, bids_basename + '-ave.fif') fname_trans = op.join(deriv_path, 'sub-{}'.format(subject) + '-trans.fif') fname_fwd = op.join(deriv_path, bids_basename + '-fwd.fif') msg = f'Input: {fname_evoked}, Output: {fname_fwd}' logger.info(gen_log_message(message=msg, step=10, subject=subject, session=session)) # Find the raw data file # XXX : maybe simplify bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=config.get_runs()[0], processing=config.proc, recording=config.rec, space=config.space) trans = get_head_mri_trans(bids_basename=bids_basename, bids_root=config.bids_root) mne.write_trans(fname_trans, trans) src = mne.setup_source_space(subject, spacing=config.spacing, subjects_dir=config.get_fs_subjects_dir(), add_dist=False) evoked = mne.read_evokeds(fname_evoked, condition=0) # Here we only use 3-layers BEM only if EEG is available. if 'eeg' in config.ch_types: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3, 0.006, 0.3), subjects_dir=config.get_fs_subjects_dir()) else: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3,), subjects_dir=config.get_fs_subjects_dir()) bem = mne.make_bem_solution(model) fwd = mne.make_forward_solution(evoked.info, trans, src, bem, mindist=config.mindist) mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
def run_forward(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, check=False) fname_evoked = bids_basename.copy().update(kind='ave', extension='.fif') fname_trans = bids_basename.copy().update(kind='trans', extension='.fif') fname_fwd = bids_basename.copy().update(kind='fwd', extension='.fif') msg = f'Input: {fname_evoked}, Output: {fname_fwd}' logger.info( gen_log_message(message=msg, step=10, subject=subject, session=session)) # Find the raw data file trans = get_head_mri_trans(bids_basename=(bids_basename.copy().update( run=config.get_runs()[0], prefix=None)), bids_root=config.bids_root) mne.write_trans(fname_trans, trans) src = mne.setup_source_space(subject, spacing=config.spacing, subjects_dir=config.get_fs_subjects_dir(), add_dist=False) evoked = mne.read_evokeds(fname_evoked, condition=0) # Here we only use 3-layers BEM only if EEG is available. if 'eeg' in config.ch_types: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3, 0.006, 0.3), subjects_dir=config.get_fs_subjects_dir()) else: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3, ), subjects_dir=config.get_fs_subjects_dir()) bem = mne.make_bem_solution(model) fwd = mne.make_forward_solution(evoked.info, trans, src, bem, mindist=config.mindist) mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
def main(): """Run grp ave.""" msg = 'Running Step 13: Grand-average source estimates' logger.info(gen_log_message(step=13, message=msg)) mne.datasets.fetch_fsaverage(subjects_dir=config.get_fs_subjects_dir()) parallel, run_func, _ = parallel_func(morph_stc, n_jobs=config.N_JOBS) all_morphed_stcs = parallel(run_func(subject, session) for subject, session in itertools.product(config.get_subjects(), config.get_sessions())) all_morphed_stcs = [morphed_stcs for morphed_stcs, subject in zip(all_morphed_stcs, config.get_subjects())] mean_morphed_stcs = map(sum, zip(*all_morphed_stcs)) subject = 'average' # XXX to fix if config.get_sessions(): session = config.get_sessions()[0] else: session = None deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space, prefix=deriv_path, check=False) for condition, this_stc in zip(config.conditions, mean_morphed_stcs): this_stc /= len(all_morphed_stcs) method = config.inverse_method cond_str = condition.replace(op.sep, '').replace('_', '') inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. morph_str = 'morph2fsaverage' fname_stc_avg = bids_basename.copy().update( kind=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}') this_stc.save(fname_stc_avg) msg = 'Completed Step 13: Grand-average source estimates' logger.info(gen_log_message(step=13, message=msg))
def run_inverse(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, extension='.fif', check=False) fname_ave = bids_basename.copy().update(kind='ave') fname_fwd = bids_basename.copy().update(kind='fwd') fname_cov = bids_basename.copy().update(kind='cov') fname_inv = bids_basename.copy().update(kind='inv') evokeds = mne.read_evokeds(fname_ave) cov = mne.read_cov(fname_cov) forward = mne.read_forward_solution(fname_fwd) info = evokeds[0].info inverse_operator = make_inverse_operator(info, forward, cov, loose=0.2, depth=0.8, rank='info') write_inverse_operator(fname_inv, inverse_operator) # Apply inverse snr = 3.0 lambda2 = 1.0 / snr**2 for condition, evoked in zip(config.conditions, evokeds): method = config.inverse_method pick_ori = None cond_str = condition.replace(op.sep, '').replace('_', '') inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. fname_stc = bids_basename.copy().update( kind=f'{cond_str}+{inverse_str}+{hemi_str}', extension=None) stc = apply_inverse(evoked=evoked, inverse_operator=inverse_operator, lambda2=lambda2, method=method, pick_ori=pick_ori) stc.save(fname_stc)
def run_inverse(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) fname_ave = op.join(deriv_path, bids_basename + '-ave.fif') fname_fwd = op.join(deriv_path, bids_basename + '-fwd.fif') fname_cov = op.join(deriv_path, bids_basename + '-cov.fif') fname_inv = op.join(deriv_path, bids_basename + '-inv.fif') evokeds = mne.read_evokeds(fname_ave) cov = mne.read_cov(fname_cov) forward = mne.read_forward_solution(fname_fwd) info = evokeds[0].info inverse_operator = make_inverse_operator(info, forward, cov, loose=0.2, depth=0.8, rank='info') write_inverse_operator(fname_inv, inverse_operator) # Apply inverse snr = 3.0 lambda2 = 1.0 / snr**2 for condition, evoked in zip(config.conditions, evokeds): method = config.inverse_method pick_ori = None cond_str = 'cond-%s' % condition.replace(op.sep, '') inverse_str = 'inverse-%s' % method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. fname_stc = op.join( deriv_path, '_'.join([bids_basename, cond_str, inverse_str, hemi_str])) stc = apply_inverse(evoked=evoked, inverse_operator=inverse_operator, lambda2=lambda2, method=method, pick_ori=pick_ori) stc.save(fname_stc)
def run_ssp(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) # compute SSP on first run of raw run = config.get_runs()[0] bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=run, processing=config.proc, recording=config.rec, space=config.space) # Prepare a name to save the data raw_fname_in = op.join(deriv_path, bids_basename + '_filt_raw.fif') # when saving proj, use bids_basename=None bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) proj_fname_out = op.join(deriv_path, bids_basename + '_ssp-proj.fif') msg = f'Input: {raw_fname_in}, Output: {proj_fname_out}' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) raw = mne.io.read_raw_fif(raw_fname_in) # XXX : n_xxx should be options in config msg = 'Computing SSPs for ECG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) ecg_projs, ecg_events = \ compute_proj_ecg(raw, n_grad=1, n_mag=1, n_eeg=0, average=True) msg = 'Computing SSPs for EOG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) eog_projs, eog_events = \ compute_proj_eog(raw, n_grad=1, n_mag=1, n_eeg=1, average=True) mne.write_proj(proj_fname_out, eog_projs + ecg_projs)
def run_time_decoding(subject, condition1, condition2, session=None): msg = f'Contrasting conditions: {condition1} – {condition2}' logger.info( gen_log_message(message=msg, step=8, subject=subject, session=session)) deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) fname_in = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, kind='epo', extension='.fif', check=False) epochs = mne.read_epochs(fname_in) # We define the epochs and the labels epochs = mne.concatenate_epochs([epochs[condition1], epochs[condition2]]) epochs.apply_baseline() # Get the data and labels X = epochs.get_data() n_cond1 = len(epochs[condition1]) n_cond2 = len(epochs[condition2]) y = np.r_[np.ones(n_cond1), np.zeros(n_cond2)] se = SlidingEstimator(make_pipeline( StandardScaler(), LogisticRegression(solver='liblinear', random_state=config.random_state)), scoring=config.decoding_metric, n_jobs=config.N_JOBS) scores = cross_val_multiscore(se, X=X, y=y, cv=config.decoding_n_splits) # let's save the scores now a_vs_b = f'{condition1}-{condition2}'.replace(op.sep, '') processing = f'{a_vs_b}+{config.decoding_metric}' processing = processing.replace('_', '-').replace('-', '') fname_td = fname_in.copy().update(kind='decoding', processing=processing, extension='.mat') savemat(fname_td, {'scores': scores, 'times': epochs.times})
def run_time_decoding(subject, condition1, condition2, session=None): msg = f'Contrasting conditions: {condition1} – {condition2}' logger.info( gen_log_message(message=msg, step=8, subject=subject, session=session)) deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) fname_in = op.join(deriv_path, bids_basename + '-epo.fif') epochs = mne.read_epochs(fname_in) # We define the epochs and the labels epochs = mne.concatenate_epochs([epochs[condition1], epochs[condition2]]) epochs.apply_baseline() # Get the data and labels X = epochs.get_data() n_cond1 = len(epochs[condition1]) n_cond2 = len(epochs[condition2]) y = np.r_[np.ones(n_cond1), np.zeros(n_cond2)] # Use AUC because chance level is same regardless of the class balance se = SlidingEstimator(make_pipeline( StandardScaler(), LogisticRegression(solver='liblinear', random_state=config.random_state)), scoring=config.decoding_metric, n_jobs=config.N_JOBS) scores = cross_val_multiscore(se, X=X, y=y, cv=config.decoding_n_splits) # let's save the scores now a_vs_b = '%s_vs_%s' % (condition1, condition2) a_vs_b = a_vs_b.replace(op.sep, '') fname_td = op.join( config.bids_root, 'derivatives', config.PIPELINE_NAME, '%s_%s_%s_%s.mat' % (subject, config.study_name, a_vs_b, config.decoding_metric)) savemat(fname_td, {'scores': scores, 'times': epochs.times})
def apply_ssp(subject, session=None): # load epochs to reject ICA components # compute SSP on first run of raw deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path) fname_in = bids_basename.copy().update(kind='epo', extension='.fif', check=False) fname_out = bids_basename.copy().update(kind='epo', processing='clean', extension='.fif', check=False) epochs = mne.read_epochs(fname_in, preload=True) msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) proj_fname_in = bids_basename.copy().update(kind='proj', extension='.fif', check=False) msg = f'Reading SSP projections from : {proj_fname_in}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) projs = mne.read_proj(proj_fname_in) epochs.add_proj(projs).apply_proj() msg = 'Saving epochs' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) epochs.save(fname_out, overwrite=True)
def run_time_frequency(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, check=False) processing = None if config.use_ica or config.use_ssp: processing = 'clean' fname_in = bids_basename.copy().update(kind='epo', processing=processing, extension='.fif') msg = f'Input: {fname_in}' logger.info( gen_log_message(message=msg, step=9, subject=subject, session=session)) epochs = mne.read_epochs(fname_in) for condition in config.time_frequency_conditions: this_epochs = epochs[condition] power, itc = mne.time_frequency.tfr_morlet(this_epochs, freqs=freqs, return_itc=True, n_cycles=n_cycles) condition_str = condition.replace(op.sep, '').replace('_', '') power_fname_out = bids_basename.copy().update( kind=f'power+{condition_str}+tfr', extension='.h5') itc_fname_out = bids_basename.copy().update( kind=f'itc+{condition_str}+tfr', extension='.h5') power.save(power_fname_out, overwrite=True) itc.save(itc_fname_out, overwrite=True)
def run_time_frequency(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) if config.use_ica or config.use_ssp: extension = '_cleaned-epo' else: extension = '-epo' fname_in = op.join(deriv_path, bids_basename + '%s.fif' % extension) msg = f'Input: {fname_in}' logger.info( gen_log_message(message=msg, step=9, subject=subject, session=session)) epochs = mne.read_epochs(fname_in) for condition in config.time_frequency_conditions: this_epochs = epochs[condition] power, itc = mne.time_frequency.tfr_morlet(this_epochs, freqs=freqs, return_itc=True, n_cycles=n_cycles) power_fname_out = \ op.join(deriv_path, bids_basename + '_power_%s-tfr.h5' % (condition.replace(op.sep, ''))) itc_fname_out = \ op.join(deriv_path, bids_basename + '_itc_%s-tfr.h5' % (condition.replace(op.sep, ''))) power.save(power_fname_out, overwrite=True) itc.save(itc_fname_out, overwrite=True)
def morph_stc(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) morphed_stcs = [] for condition in config.conditions: method = config.inverse_method cond_str = 'cond-%s' % condition.replace(op.sep, '') inverse_str = 'inverse-%s' % method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. morph_str = 'morph-fsaverage' fname_stc = op.join( deriv_path, '_'.join([bids_basename, cond_str, inverse_str, hemi_str])) fname_stc_fsaverage = op.join( deriv_path, '_'.join( [bids_basename, cond_str, inverse_str, morph_str, hemi_str])) stc = mne.read_source_estimate(fname_stc) morph = mne.compute_source_morph( stc, subject_from=subject, subject_to='fsaverage', subjects_dir=config.get_fs_subjects_dir()) stc_fsaverage = morph.apply(stc) stc_fsaverage.save(fname_stc_fsaverage) morphed_stcs.append(stc_fsaverage) del fname_stc, fname_stc_fsaverage return morphed_stcs
def apply_ssp(subject, session=None): # load epochs to reject ICA components # compute SSP on first run of raw deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) fname_in = op.join(deriv_path, bids_basename + '-epo.fif') fname_out = op.join(deriv_path, bids_basename + '_cleaned-epo.fif') epochs = mne.read_epochs(fname_in, preload=True) msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) proj_fname_in = op.join(deriv_path, bids_basename + '_ssp-proj.fif') msg = f'Reading SSP projections from : {proj_fname_in}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) projs = mne.read_proj(proj_fname_in) epochs.add_proj(projs).apply_proj() msg = 'Saving epochs' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) epochs.save(fname_out, overwrite=True)
def morph_stc(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, check=False) morphed_stcs = [] for condition in config.conditions: method = config.inverse_method cond_str = condition.replace(op.sep, '').replace('_', '') inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. morph_str = 'morph2fsaverage' fname_stc = bids_basename.copy().update( kind=f'{cond_str}+{inverse_str}+{hemi_str}') fname_stc_fsaverage = bids_basename.copy().update( kind=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}') stc = mne.read_source_estimate(fname_stc) morph = mne.compute_source_morph( stc, subject_from=subject, subject_to='fsaverage', subjects_dir=config.get_fs_subjects_dir()) stc_fsaverage = morph.apply(stc) stc_fsaverage.save(fname_stc_fsaverage) morphed_stcs.append(stc_fsaverage) del fname_stc, fname_stc_fsaverage return morphed_stcs
def compute_cov_from_epochs(subject, session, tmin, tmax): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space, prefix=deriv_path, check=False) processing = None if config.use_ica or config.use_ssp: processing = 'clean' epo_fname = bids_basename.copy().update(kind='epo', processing=processing, extension='.fif') cov_fname = bids_basename.copy().update(kind='cov', extension='.fif') msg = (f"Computing regularized covariance based on epochs' baseline " f"periods. Input: {epo_fname}, Output: {cov_fname}") logger.info( gen_log_message(message=msg, step=11, subject=subject, session=session)) epochs = mne.read_epochs(epo_fname, preload=True) cov = mne.compute_covariance(epochs, tmin=tmin, tmax=tmax, method='shrunk', rank='info') cov.save(cov_fname)
def load_data(bids_basename): # read_raw_bids automatically # - populates bad channels using the BIDS channels.tsv # - sets channels types according to BIDS channels.tsv `type` column # - sets raw.annotations using the BIDS events.tsv params = _parse_bids_filename(bids_basename, verbose=False) subject = params['sub'] session = params['ses'] extra_params = dict() if config.allow_maxshield: extra_params['allow_maxshield'] = config.allow_maxshield raw = read_raw_bids(bids_basename=bids_basename, bids_root=config.bids_root, extra_params=extra_params, kind=config.get_kind()) # XXX hack to deal with dates that fif files cannot handle if config.daysback is not None: raw.anonymize(daysback=config.daysback) if subject != 'emptyroom': # Crop the data. if config.crop is not None: raw.crop(*config.crop) # Rename events. if config.rename_events: rename_events(raw=raw, subject=subject, session=session) raw.load_data() if hasattr(raw, 'fix_mag_coil_types'): raw.fix_mag_coil_types() return raw
def plot_auto_scores(subject, session): """Plot automated bad channel detection scores. """ import json_tricks deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) fname_scores = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space, kind='scores', extension='.json', prefix=deriv_path, check=False) all_figs = [] all_captions = [] for run in config.get_runs(): with open(fname_scores.update(run=run), 'r') as f: auto_scores = json_tricks.load(f) figs = config.plot_auto_scores(auto_scores) all_figs.extend(figs) # Could be more than 1 fig, e.g. "grad" and "mag" captions = [f'Run {run}'] * len(figs) all_captions.extend(captions) return all_figs, all_captions
def run_ica(subject, session=None): """Run ICA.""" deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, recording=config.rec, space=config.space, prefix=deriv_path) raw_list = list() msg = 'Loading filtered raw data' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) for run in config.get_runs(): raw_fname_in = bids_basename.copy().update(run=run, processing='filt', kind=config.get_kind(), extension='.fif') raw = mne.io.read_raw_fif(raw_fname_in, preload=True) raw_list.append(raw) msg = 'Concatenating runs' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) raw = mne.concatenate_raws(raw_list) events, event_id = mne.events_from_annotations(raw) if config.get_kind() == 'eeg': raw.set_eeg_reference(projection=True) del raw_list # don't reject based on EOG to keep blink artifacts # in the ICA computation. reject_ica = config.get_reject() if reject_ica and 'eog' in reject_ica: reject_ica = dict(reject_ica) del reject_ica['eog'] # produce high-pass filtered version of the data for ICA raw_ica = raw.copy().filter(l_freq=1., h_freq=None) epochs_for_ica = mne.Epochs(raw_ica, events, event_id, config.tmin, config.tmax, proj=True, baseline=config.baseline, preload=True, decim=config.decim, reject=reject_ica) # get number of components for ICA # compute_rank requires 0.18 # n_components_meg = (mne.compute_rank(epochs_for_ica.copy() # .pick_types(meg=True)))['meg'] n_components_meg = 0.999 n_components = {'meg': n_components_meg, 'eeg': 0.999} kind = config.get_kind() msg = f'Running ICA for {kind}' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) if config.ica_algorithm == 'picard': fit_params = dict(fastica_it=5) elif config.ica_algorithm == 'extended_infomax': fit_params = dict(extended=True) elif config.ica_algorithm == 'fastica': fit_params = None ica = ICA(method=config.ica_algorithm, random_state=config.random_state, n_components=n_components[kind], fit_params=fit_params, max_iter=config.ica_max_iterations) ica.fit(epochs_for_ica, decim=config.ica_decim) msg = (f'Fit {ica.n_components_} components (explaining at least ' f'{100*n_components[kind]:.1f}% of the variance)') logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) # Save ICA ica_fname = bids_basename.copy().update(run=None, kind=f'{kind}-ica', extension='.fif') ica.save(ica_fname) if config.interactive: # plot ICA components to html report report_fname = bids_basename.copy().update(run=None, kind=f'{kind}-ica', extension='.html') report = Report(report_fname, verbose=False) for idx in range(0, ica.n_components_): figure = ica.plot_properties(epochs_for_ica, picks=idx, psd_args={'fmax': 60}, show=False) report.add_figs_to_section(figure, section=subject, captions=(kind.upper() + ' - ICA Components')) report.save(report_fname, overwrite=True, open_browser=False)
def run_maxwell_filter(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) os.makedirs(deriv_path, exist_ok=True) for run_idx, run in enumerate(config.get_runs()): bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=run, processing=config.proc, recording=config.rec, space=config.space) raw = load_data(bids_basename) if run_idx == 0: dev_head_t = raw.info['dev_head_t'] # Re-use in all runs. # Auto-detect bad channels. if config.find_flat_channels_meg or config.find_noisy_channels_meg: find_bad_channels(raw=raw, subject=subject, session=session, task=config.get_task(), run=run) # Maxwell-filter experimental data. if config.use_maxwell_filter: msg = 'Applying Maxwell filter to experimental data.' logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) # Warn if no bad channels are set before Maxwell filter if not raw.info['bads']: msg = '\nFound no bad channels. \n ' logger.warn( gen_log_message(message=msg, subject=subject, step=1, session=session)) if config.mf_st_duration: msg = ' st_duration=%d' % (config.mf_st_duration) logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) # Keyword arguments shared between Maxwell filtering of the # experimental and the empty-room data. common_mf_kws = dict(calibration=config.mf_cal_fname, cross_talk=config.mf_ctc_fname, st_duration=config.mf_st_duration, origin=config.mf_head_origin, coord_frame='head', destination=dev_head_t) raw_sss = mne.preprocessing.maxwell_filter(raw, **common_mf_kws) raw_out = raw_sss raw_fname_out = op.join(deriv_path, f'{bids_basename}_sss_raw.fif') else: msg = ('Not applying Maxwell filter.\nIf you wish to apply it, ' 'set use_maxwell_filter=True in your configuration.') logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) raw_out = raw raw_fname_out = op.join(deriv_path, f'{bids_basename}_nosss_raw.fif') raw_out.save(raw_fname_out, overwrite=True) if config.interactive: raw_out.plot(n_channels=50, butterfly=True) # Empty-room processing. # # We pick the empty-room recording closest in time to the first run # of the experimental session. if run_idx == 0 and config.noise_cov == 'emptyroom': msg = 'Processing empty-room recording …' logger.info( gen_log_message(step=1, subject=subject, session=session, message=msg)) bids_basename_er_in = get_matched_empty_room( bids_basename=bids_basename, bids_root=config.bids_root) raw_er = load_data(bids_basename_er_in) raw_er.info['bads'] = [ ch for ch in raw.info['bads'] if ch.startswith('MEG') ] # Maxwell-filter empty-room data. if config.use_maxwell_filter: msg = 'Applying Maxwell filter to empty-room recording' logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) # We want to ensure we use the same coordinate frame origin in # empty-room and experimental data processing. To do this, we # inject the sensor locations and the head <> device transform # into the empty-room recording's info, and leave all other # parameters the same as for the experimental data. This is not # very clean, as we normally should not alter info manually, # except for info['bads']. Will need improvement upstream in # MNE-Python. raw_er.info['dig'] = raw.info['dig'] raw_er.info['dev_head_t'] = dev_head_t raw_er_sss = mne.preprocessing.maxwell_filter( raw_er, **common_mf_kws) # Perform a sanity check: empty-room rank should match the # experimental data rank after Maxwell filtering. rank_exp = mne.compute_rank(raw, rank='info')['meg'] rank_er = mne.compute_rank(raw_er, rank='info')['meg'] if not np.isclose(rank_exp, rank_er): msg = (f'Experimental data rank {rank_exp:.1f} does not ' f'match empty-room data rank {rank_er:.1f} after ' f'Maxwell filtering. This indicates that the data ' f'were processed differenlty.') raise RuntimeError(msg) raw_er_out = raw_er_sss raw_er_fname_out = op.join( deriv_path, f'{bids_basename}_emptyroom_sss_raw.fif') else: raw_er_out = raw_er raw_er_fname_out = op.join( deriv_path, f'{bids_basename}_emptyroom_nosss_raw.fif') raw_er_out.save(raw_er_fname_out, overwrite=True)
def find_bad_channels(raw, subject, session, task, run): if (config.find_flat_channels_meg and not config.find_noisy_channels_meg): msg = 'Finding flat channels.' elif (config.find_noisy_channels_meg and not config.find_flat_channels_meg): msg = 'Finding noisy channels using Maxwell filtering.' else: msg = ('Finding flat channels, and noisy channels using ' 'Maxwell filtering.') logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) raw_lp_filtered_for_maxwell = (raw.copy().filter(l_freq=None, h_freq=40)) auto_noisy_chs, auto_flat_chs = find_bad_channels_maxwell( raw=raw_lp_filtered_for_maxwell, calibration=config.mf_cal_fname, cross_talk=config.mf_ctc_fname) del raw_lp_filtered_for_maxwell preexisting_bads = raw.info['bads'].copy() bads = preexisting_bads.copy() if config.find_flat_channels_meg: msg = f'Found {len(auto_flat_chs)} flat channels.' logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) bads.extend(auto_flat_chs) if config.find_noisy_channels_meg: msg = f'Found {len(auto_noisy_chs)} noisy channels.' logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) bads.extend(auto_noisy_chs) bads = sorted(set(bads)) raw.info['bads'] = bads msg = f'Marked {len(raw.info["bads"])} channels as bad.' logger.info( gen_log_message(message=msg, step=1, subject=subject, session=session)) # Write the bad channels to disk. deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=run, processing=config.proc, recording=config.rec, space=config.space) bads_tsv_fname = op.join(deriv_path, f'{bids_basename}_bad_channels.tsv') bads_for_tsv = [] reasons = [] if config.find_flat_channels_meg: bads_for_tsv.extend(auto_flat_chs) reasons.extend(['auto-flat'] * len(auto_flat_chs)) preexisting_bads = set(preexisting_bads) - set(auto_flat_chs) if config.find_noisy_channels_meg: bads_for_tsv.extend(auto_noisy_chs) reasons.extend(['auto-noisy'] * len(auto_noisy_chs)) preexisting_bads = set(preexisting_bads) - set(auto_noisy_chs) preexisting_bads = list(preexisting_bads) if preexisting_bads: bads_for_tsv.extend(preexisting_bads) reasons.extend(['pre-existing (before mne-study-template was run)'] * len(preexisting_bads)) tsv_data = pd.DataFrame(dict(name=bads_for_tsv, reason=reasons)) tsv_data = tsv_data.sort_values(by='name') tsv_data.to_csv(bads_tsv_fname, sep='\t', index=False)
def apply_ica(subject, run, session): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) fname_in = op.join(deriv_path, bids_basename + '-epo.fif') fname_out = op.join(deriv_path, bids_basename + '_cleaned-epo.fif') # load epochs to reject ICA components epochs = mne.read_epochs(fname_in, preload=True) msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) # load first run of raw data for ecg / eog epochs msg = 'Loading first run from raw data' logger.debug( gen_log_message(message=msg, step=5, subject=subject, session=session)) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=config.get_runs()[0], processing=config.proc, recording=config.rec, space=config.space) if config.use_maxwell_filter: raw_fname_in = op.join(deriv_path, bids_basename + '_sss_raw.fif') else: raw_fname_in = \ op.join(deriv_path, bids_basename + '_filt_raw.fif') raw = mne.io.read_raw_fif(raw_fname_in, preload=True) # run ICA on MEG and EEG picks_meg = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') picks_eeg = mne.pick_types(raw.info, meg=False, eeg=True, eog=False, stim=False, exclude='bads') all_picks = {'meg': picks_meg, 'eeg': picks_eeg} for ch_type in config.ch_types: report = None picks = all_picks[ch_type] # Load ICA fname_ica = op.join(deriv_path, f'bids_basename_{ch_type}-ica.fif') msg = f'Reading ICA: {fname_ica}' logger.debug( gen_log_message(message=msg, step=5, subject=subject, session=session)) ica = read_ica(fname=fname_ica) pick_ecg = mne.pick_types(raw.info, meg=False, eeg=False, ecg=True, eog=False) # ECG # either needs an ecg channel, or avg of the mags (i.e. MEG data) ecg_inds = list() if pick_ecg or ch_type == 'meg': picks_ecg = np.concatenate([picks, pick_ecg]) # Create ecg epochs if ch_type == 'meg': reject = { 'mag': config.reject['mag'], 'grad': config.reject['grad'] } elif ch_type == 'eeg': reject = {'eeg': config.reject['eeg']} ecg_epochs = create_ecg_epochs(raw, picks=picks_ecg, reject=reject, baseline=(None, 0), tmin=-0.5, tmax=0.5) ecg_average = ecg_epochs.average() ecg_inds, scores = \ ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=config.ica_ctps_ecg_threshold) del ecg_epochs report_fname = \ op.join(deriv_path, bids_basename + f'_{ch_type}-reject_ica.html') report = Report(report_fname, verbose=False) # Plot r score report.add_figs_to_section( ica.plot_scores(scores, exclude=ecg_inds, show=config.interactive), captions=ch_type.upper() + ' - ECG - R scores') # Plot source time course report.add_figs_to_section( ica.plot_sources(ecg_average, exclude=ecg_inds, show=config.interactive), captions=ch_type.upper() + ' - ECG - Sources time course') # Plot source time course report.add_figs_to_section( ica.plot_overlay(ecg_average, exclude=ecg_inds, show=config.interactive), captions=ch_type.upper() + ' - ECG - Corrections') else: # XXX : to check when EEG only is processed msg = ('No ECG channel is present. Cannot automate IC detection ' 'for ECG') logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) # EOG pick_eog = mne.pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True) eog_inds = list() if pick_eog.any(): msg = 'Using EOG channel' logger.debug( gen_log_message(message=msg, step=5, subject=subject, session=session)) picks_eog = np.concatenate([picks, pick_eog]) # Create eog epochs eog_epochs = create_eog_epochs(raw, picks=picks_eog, reject=None, baseline=(None, 0), tmin=-0.5, tmax=0.5) eog_average = eog_epochs.average() eog_inds, scores = ica.find_bads_eog(eog_epochs, threshold=3.0) del eog_epochs params = dict(exclude=eog_inds, show=config.interactive) # Plot r score report.add_figs_to_section(ica.plot_scores(scores, **params), captions=ch_type.upper() + ' - EOG - ' + 'R scores') # Plot source time course report.add_figs_to_section(ica.plot_sources(eog_average, **params), captions=ch_type.upper() + ' - EOG - ' + 'Sources time course') # Plot source time course report.add_figs_to_section(ica.plot_overlay(eog_average, **params), captions=ch_type.upper() + ' - EOG - ' + 'Corrections') report.save(report_fname, overwrite=True, open_browser=False) else: msg = ('No EOG channel is present. Cannot automate IC detection ' 'for EOG') logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) ica_reject = (list(ecg_inds) + list(eog_inds) + list(config.rejcomps_man[subject][ch_type])) # now reject the components msg = f'Rejecting from {ch_type}: {ica_reject}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) epochs = ica.apply(epochs, exclude=ica_reject) msg = 'Saving cleaned epochs' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) epochs.save(fname_out) if report is not None: fig = ica.plot_overlay(raw, exclude=ica_reject, show=config.interactive) report.add_figs_to_section(fig, captions=ch_type.upper() + ' - ALL(epochs) - Corrections') if config.interactive: epochs.plot_image(combine='gfp', group_by='type', sigma=2., cmap="YlGnBu_r", show=config.interactive)
def run_filter(subject, run=None, session=None): """Filter data from a single subject.""" kind = config.get_kind() deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=kind) # Construct the basenames of the files we wish to load, and of the empty- # room recording we wish to save. # The basenames of the empty-room recording output file does not contain # the "run" entity. bids_basename = BIDSPath(subject=subject, run=run, session=session, task=config.get_task(), acquisition=config.acq, processing=config.proc, recording=config.rec, space=config.space, prefix=deriv_path, kind=kind) bids_er_out_basename = bids_basename.copy().update(run=None) # Prepare a name to save the data raw_fname_in = bids_basename.copy().update(extension='.fif') raw_er_fname_in = bids_basename.copy().update( task='noise', run=None, extension='.fif') if config.use_maxwell_filter: raw_fname_in = raw_fname_in.update(processing='sss') raw_er_fname_in = raw_er_fname_in.update(processing='sss') raw_fname_out = bids_basename.copy().update( processing='filt', extension='.fif') raw_er_fname_out = bids_er_out_basename.copy().update( processing='filt', task='noise', extension='.fif') msg = f'Input: {raw_fname_in}, Output: {raw_fname_out}' logger.info(gen_log_message(message=msg, step=2, subject=subject, session=session, run=run,)) raw = mne.io.read_raw_fif(raw_fname_in) raw.load_data() # Band-pass the data channels (MEG and EEG) msg = (f'Filtering experimental data between {config.l_freq} and ' f'{config.h_freq} Hz') logger.info(gen_log_message(message=msg, step=2, subject=subject, session=session, run=run)) filter_kws = dict(l_freq=config.l_freq, h_freq=config.h_freq, l_trans_bandwidth=config.l_trans_bandwidth, h_trans_bandwidth=config.h_trans_bandwidth, filter_length='auto', phase='zero', fir_window='hamming', fir_design='firwin') raw.filter(**filter_kws) if config.process_er: msg = 'Filtering empty-room recording.' logger.info(gen_log_message(message=msg, step=2, subject=subject, session=session, run=run,)) raw_er = mne.io.read_raw_fif(raw_er_fname_in) raw_er.load_data() raw_er.filter(**filter_kws) if config.resample_sfreq: msg = f'Resampling experimental data to {config.resample_sfreq:.1f} Hz' logger.info(gen_log_message(message=msg, step=2, subject=subject, session=session, run=run,)) raw.resample(config.resample_sfreq, npad='auto') if config.process_er: msg = 'Resampling empty-room recording.' logger.info(gen_log_message(message=msg, step=2, subject=subject, session=session, run=run,)) raw_er.resample(config.resample_sfreq, npad='auto') raw.save(raw_fname_out, overwrite=True) if config.process_er: raw_er.save(raw_er_fname_out, overwrite=True) if config.interactive: # Plot raw data and power spectral density. raw.plot(n_channels=50, butterfly=True) fmax = 1.5 * config.h_freq if config.h_freq is not None else np.inf raw.plot_psd(fmax=fmax) if config.process_er: raw_er.plot(n_channels=50, butterfly=True) raw_er.plot_psd(fmax=fmax)
msg = 'Running Step 7: Grand-average sensor data' logger.info(gen_log_message(step=7, message=msg)) # Container for all conditions: all_evokeds = defaultdict(list) # XXX to fix if config.get_sessions(): session = config.get_sessions()[0] else: session = None for subject in config.get_subjects(): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) fname_in = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, kind='ave', extension='.fif', check=False) msg = f'Input: {fname_in}' logger.info(gen_log_message(message=msg, step=7, subject=subject,