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_epochs(subject, session=None): """Extract epochs for one subject.""" raw_list = list() bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root) for run in config.get_runs(): # Prepare a name to save the data raw_fname_in = bids_path.copy().update(run=run, processing='filt', suffix='raw', check=False) if raw_fname_in.copy().update(split='01').fpath.exists(): raw_fname_in.update(split='01') msg = f'Loading filtered raw data from {raw_fname_in}' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session, run=run)) 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=3, subject=subject, session=session)) if len(raw_list) == 1: # avoid extra memory usage raw = raw_list[0] else: raw = mne.concatenate_raws(raw_list) events, event_id = mne.events_from_annotations(raw) if "eeg" in config.ch_types: projection = True if config.eeg_reference == 'average' else False raw.set_eeg_reference(config.eeg_reference, projection=projection) del raw_list # Construct metadata from the epochs # Add here if you need to attach a pandas dataframe as metadata # to your epochs object: # https://martinos.org/mne/dev/auto_tutorials/plot_metadata_epochs.html # Epoch the data msg = 'Epoching' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session)) epochs = mne.Epochs(raw, events=events, event_id=event_id, tmin=config.epochs_tmin, tmax=config.epochs_tmax, proj=True, baseline=config.baseline, preload=False, decim=config.decim, reject=config.get_reject(), reject_tmin=config.reject_tmin, reject_tmax=config.reject_tmax) msg = 'Writing epochs to disk' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session)) epochs_fname = bids_path.copy().update(suffix='epo', check=False) epochs.save(epochs_fname, overwrite=True) if config.interactive: epochs.plot() epochs.plot_image(combine='gfp', sigma=2., cmap='YlGnBu_r')
def run_epochs(subject, session=None): """Extract epochs for one subject.""" raw_list = list() deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) for run in 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) # Prepare a name to save the data raw_fname_in = \ op.join(deriv_path, bids_basename + '_filt_raw.fif') msg = f'Loading filtered raw data from {raw_fname_in}' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session, run=run)) 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=3, subject=subject, session=session)) raw = mne.concatenate_raws(raw_list) events, event_id = mne.events_from_annotations(raw) if "eeg" in config.ch_types: raw.set_eeg_reference(projection=True) del raw_list meg = False if 'meg' in config.ch_types: meg = True elif 'grad' in config.ch_types: meg = 'grad' elif 'mag' in config.ch_types: meg = 'mag' eeg = config.get_kind() == 'eeg' picks = mne.pick_types(raw.info, meg=meg, eeg=eeg, stim=True, eog=True, exclude=()) # Construct metadata from the epochs # Add here if you need to attach a pandas dataframe as metadata # to your epochs object: # https://martinos.org/mne/dev/auto_tutorials/plot_metadata_epochs.html # Epoch the data msg = 'Epoching' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session)) epochs = mne.Epochs(raw, events, event_id, config.tmin, config.tmax, proj=True, picks=picks, baseline=config.baseline, preload=False, decim=config.decim, reject=config.get_reject()) msg = 'Writing epochs to disk' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session)) 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) epochs_fname = \ op.join(deriv_path, bids_basename + '-epo.fif') epochs.save(epochs_fname, overwrite=True) if config.interactive: epochs.plot() epochs.plot_image(combine='gfp', picks=config.ch_types, sigma=2., cmap='YlGnBu_r')
def run_epochs(subject, session=None): """Extract epochs for one subject.""" raw_list = list() bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root) for run in config.get_runs(): # Prepare a name to save the data raw_fname_in = bids_path.copy().update(run=run, processing='filt', suffix='raw', check=False) if raw_fname_in.copy().update(split='01').fpath.exists(): raw_fname_in.update(split='01') msg = f'Loading filtered raw data from {raw_fname_in}' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session, run=run)) 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=3, subject=subject, session=session)) if len(raw_list) == 1: # avoid extra memory usage raw = raw_list[0] else: raw = mne.concatenate_raws(raw_list) events, event_id = mne.events_from_annotations(raw) if "eeg" in config.ch_types: projection = True if config.eeg_reference == 'average' else False raw.set_eeg_reference(config.eeg_reference, projection=projection) del raw_list # Construct metadata from the epochs if config.epochs_metadata_tmin is None: epochs_metadata_tmin = config.epochs_tmin else: epochs_metadata_tmin = config.epochs_metadata_tmin if config.epochs_metadata_tmax is None: epochs_metadata_tmax = config.epochs_tmax else: epochs_metadata_tmax = config.epochs_metadata_tmax metadata, _, _ = mne.epochs.make_metadata( events=events, event_id=event_id, tmin=epochs_metadata_tmin, tmax=epochs_metadata_tmax, keep_first=config.epochs_metadata_keep_first, keep_last=config.epochs_metadata_keep_last, sfreq=raw.info['sfreq']) # Epoch the data msg = (f'Creating epochs with duration: ' f'[{config.epochs_tmin}, {config.epochs_tmin}] sec') logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session)) epochs = mne.Epochs(raw, events=events, event_id=event_id, tmin=config.epochs_tmin, tmax=config.epochs_tmax, proj=True, baseline=None, preload=False, decim=config.decim, reject=config.get_reject(), reject_tmin=config.reject_tmin, reject_tmax=config.reject_tmax, metadata=metadata, event_repeated=config.event_repeated) msg = 'Writing epochs to disk' logger.info( gen_log_message(message=msg, step=3, subject=subject, session=session)) epochs_fname = bids_path.copy().update(suffix='epo', check=False) epochs.save(epochs_fname, overwrite=True) if config.interactive: epochs.plot() epochs.plot_image(combine='gfp', sigma=2., cmap='YlGnBu_r')
def drop_ptp(*, cfg, subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, recording=cfg.rec, space=cfg.space, suffix='epo', extension='.fif', datatype=cfg.datatype, root=cfg.deriv_root, check=False) infile_processing = cfg.spatial_filter fname_in = bids_path.copy().update(processing=infile_processing) fname_out = bids_path.copy().update(processing='clean') msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) # Get rejection parameters and drop bad epochs epochs = mne.read_epochs(fname_in, preload=True) reject = config.get_reject(epochs=epochs) if cfg.ica_reject is not None: for ch_type, threshold in cfg.ica_reject.items(): if (ch_type in reject and threshold < reject[ch_type]): # This can only ever happen in case of # reject = 'autoreject_global' msg = (f'Adjusting PTP rejection threshold proposed by ' f'autoreject, as it is greater than ica_reject: ' f'{ch_type}: {reject[ch_type]} -> {threshold}') logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session)) reject[ch_type] = threshold msg = f'Using PTP rejection thresholds: {reject}' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) n_epochs_before_reject = len(epochs) epochs.reject_tmin = cfg.reject_tmin epochs.reject_tmax = cfg.reject_tmax epochs.drop_bad(reject=reject) n_epochs_after_reject = len(epochs) if 0 < n_epochs_after_reject < 0.5 * n_epochs_before_reject: msg = ('More than 50% of all epochs rejected. Please check the ' 'rejection thresholds.') logger.warning( **gen_log_kwargs(message=msg, subject=subject, session=session)) elif n_epochs_after_reject == 0: raise RuntimeError('No epochs remaining after peak-to-peak-based ' 'rejection. Cannot continue.') msg = 'Saving cleaned, baseline-corrected epochs …' epochs.apply_baseline(cfg.baseline) epochs.save(fname_out, overwrite=True)